Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
082f42af77 | ||
|
|
2bec610552 | ||
|
|
f3a2603309 | ||
|
|
7d10251bd9 | ||
|
|
5c7b320b04 | ||
|
|
509048da04 | ||
|
|
15f7777d78 | ||
|
|
45b1b9cf96 | ||
|
|
57314e673a | ||
|
|
0a7b8f9587 | ||
|
|
c8ff39c2ab | ||
|
|
252204a760 | ||
|
|
26fbde676e | ||
|
|
81585ec146 | ||
|
|
4ad0437730 | ||
|
|
6245fe37fc | ||
|
|
ca50872913 | ||
|
|
3c11c368a3 | ||
|
|
145709fd76 | ||
|
|
758c5de2c7 | ||
|
|
c159ff90e3 | ||
|
|
083b07fdba | ||
|
|
c6a8462ece | ||
|
|
afee0466e7 | ||
|
|
62b36cd2b4 | ||
|
|
99c5210935 | ||
|
|
75cb7f8b98 | ||
|
|
c89259e892 | ||
|
|
d40835aa18 | ||
|
|
b93c76c6c7 | ||
|
|
c29370ac61 | ||
|
|
68abeed907 | ||
|
|
11b7851b9f | ||
|
|
329791e70e | ||
|
|
b7b262be00 | ||
|
|
6a806aa10b | ||
|
|
6542b8ba55 | ||
|
|
c3bc62f1e1 | ||
|
|
8b649200d2 | ||
|
|
5f95b18e77 | ||
|
|
4d45aedc73 | ||
|
|
a038bedb12 | ||
|
|
43892dbe41 | ||
|
|
ad33abc424 | ||
|
|
290a3cea0e | ||
|
|
ca3bbb6435 | ||
|
|
704e6e0ec2 | ||
|
|
23871487e4 | ||
|
|
6e1ba9440e | ||
|
|
c284272b06 | ||
|
|
6746a54659 | ||
|
|
93be667e17 | ||
|
|
f11da6225d | ||
|
|
e28a4c6cbf | ||
|
|
fa8a2bef32 | ||
|
|
1c9d238734 | ||
|
|
2f7f4e6456 | ||
|
|
6e83ec85c7 | ||
|
|
cc561b846e | ||
|
|
4628b3b0b6 | ||
|
|
9c69fbc7d4 | ||
|
|
9047020d69 | ||
|
|
1c18d862a1 | ||
|
|
b0ddca985a | ||
|
|
996e06c451 | ||
|
|
612747203a | ||
|
|
f7853ae299 | ||
|
|
7443db3078 | ||
|
|
ad5f6cb228 | ||
|
|
1486b19ce1 | ||
|
|
3e1095f745 | ||
|
|
17039bd3c1 | ||
|
|
b5d8feab62 | ||
|
|
95b08ff7a3 | ||
|
|
ab8ae9d0c9 | ||
|
|
b4d163e144 | ||
|
|
3ccfd9a29b | ||
|
|
90504d1305 | ||
|
|
88199189a2 | ||
|
|
0b6612eacc | ||
|
|
d706f545d2 | ||
|
|
ae8d63b162 | ||
|
|
77e742e812 | ||
|
|
b2ee8b8d94 | ||
|
|
7080d85605 | ||
|
|
1275b2109f | ||
|
|
b2eab28cb9 | ||
|
|
67234ceaa6 | ||
|
|
45f9e20e97 | ||
|
|
6b7edc713a | ||
|
|
1ef8f94d67 | ||
|
|
9b0b644cd1 | ||
|
|
b233c49d73 | ||
|
|
b8d8d2f8ed | ||
|
|
731020ba0f | ||
|
|
4c00955639 | ||
|
|
cbc150905f | ||
|
|
a71b8cef73 | ||
|
|
66c67fa8d1 | ||
|
|
3ca7c70faa |
@@ -20,7 +20,8 @@
|
||||
* 结构设计合理,客户端分功能库、UI库和应用三层。应用成熟完善,开箱即用,也可把SDK嵌入其它应用。
|
||||
* 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。
|
||||
* API丰富,方便与其它服务系统的对接。
|
||||
* 拥有机器人和公众号功能。
|
||||
* 拥有机器人和公众号功能,免费的频道(公众号)管理后台。
|
||||
* 超级群组功能,可以支持万人大群。
|
||||
* 社区版IM服务和移动端免费商用,可以免费构建出完备的移动互联网应用。
|
||||
* 收费项目非常便宜,野火独有的试用模式,可以先部署到客户环境试用6个月,试用满意后再购买,避免上当受骗。
|
||||
* 技术支持专业和高效,核心研发人员及时处理issue和论坛回复。
|
||||
@@ -28,7 +29,7 @@
|
||||
## 野火开源项目
|
||||
主要包括以下项目:
|
||||
|
||||
| [GitHub仓库地址](https://github.com/wildfirechat) | [码云仓库地址](https://gitee.com/wfchat) | 说明
|
||||
| [GitHub仓库](https://github.com/wildfirechat) | [码云仓库](https://gitee.com/wfchat) | 说明
|
||||
| ------------------------------------------------------------ | ----------------------------------------------------- | --------------------------------------------------------------------------
|
||||
| [im-server](https://github.com/wildfirechat/im-server) | [im-server](https://gitee.com/wfchat/im-server) | 野火社区版IM服务,野火IM的核心服务,处理所有IM相关业务。 |
|
||||
| [app-server](https://github.com/wildfirechat/app-server) | [app-server](https://gitee.com/wfchat/app-server) | Demo应用服务,模拟客户的应用服登陆处理逻辑及部分二次开发示例。 |
|
||||
@@ -39,14 +40,15 @@
|
||||
| [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服务。 |
|
||||
| [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源码。 |
|
||||
| [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)。 |
|
||||
| [web-chat](https://github.com/wildfirechat/vue-chat) | [web-chat](https://gitee.com/wfchat/vue-chat) | 野火IM Web 端, [体验地址](https://web.wildfirechat.cn)。 |
|
||||
| [wx-chat](https://github.com/wildfirechat/wx-chat) | [wx-chat](https://gitee.com/wfchat/wx-chat) | 小程序平台的Demo(支持微信、百度、阿里、字节、QQ 等小程序平台)。 |
|
||||
| [uni-chat](https://github.com/wildfirechat/uni-chat) | [uni-chat](https://gitee.com/wfchat/uni-chat) | UniApp平台移动端应用(使用原生插件)。 |
|
||||
| [uni-wfc-client](https://github.com/wildfirechat/uni-wfc-client) | [uni-wfc-client](https://gitee.com/wfchat/uni-wfc-client) | UniApp平台原生插件。 |
|
||||
| [flutter_imclient](https://github.com/wildfirechat/flutter_imclient) | [flutter_imclient](https://gitee.com/wfchat/flutter_imclient) | Flutter平台原生插件。 |
|
||||
| [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)上架 |
|
||||
| [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/)。 |
|
||||
|
||||
## 野火开发文档
|
||||
@@ -73,34 +75,24 @@ PC客户端点[这里](https://github.com/wildfirechat/vue-pc-chat/releases)下
|
||||
|
||||
之后再部署开放平台服务、频道(公众号)服务、机器人服务、推送服务、Turn服务(音视频服务)来实现完整的应用功能,详情可以详细阅读文档。
|
||||
|
||||
## 应用截图
|
||||

|
||||
## 联系我们
|
||||
商务合作请微信联系:
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-message-view.png" width = 50% height = 50% />
|
||||
* 微信1:wildfirechat
|
||||
* 微信2:wfchat
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-contact-view.png" width = 50% height = 50% />
|
||||
## 问题交流
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-discover-view.png" width = 50% height = 50% />
|
||||
1. 如果大家发现bug,请在GitHub或码云提issue;如果有需求也请给我们提issue。
|
||||
2. 其他问题,请到[野火IM论坛](http://bbs.wildfirechat.cn/)进行交流学习
|
||||
3. 关注我们的公众号。我们有新版本发布或者有重大更新会通过公众号通知大家,另外我们也会不定期的发布一些关于野火IM的技术介绍。
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-settings-view.png" width = 50% height = 50% />
|
||||
<img src="http://static.wildfirechat.cn/wx_wfc_qrcode.jpg" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-messagelist-view.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-chat-setting-view.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-takephoto-view.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-record-voice-view.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-location-view.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-voip-view.png" width = 50% height = 50% />
|
||||
我们有核心研发工程师轮流值班处理issue和论坛,会及时处理的,疑难Bug的修改和新需求的开发我们也会尽快解决。
|
||||
|
||||
|
||||
## 编译
|
||||
由于```distribution/pom.xml```中使用了生成RPM包的plugin,所以需要本地安装有rpm。如果不需要RPM包,可以删除掉```distribution/pom.xml```文件中的RPM plugin。
|
||||
|
||||
在安装RPM后或者删除```distribution/pom.xml```文件中的RPM plugin后,执行下面命令:
|
||||
```
|
||||
mvn clean package
|
||||
```
|
||||
@@ -119,6 +111,11 @@ mvn clean package
|
||||
1. 在浏览器中输入地址 ```http://${ip}/api/version```可以看到返回一个json文件。
|
||||
2. 部署[应用服务](https://github.com/wildfirechat/app-server),配置和编译[Android客户端](https://github.com/wildfirechat/android-chat)和[iOS客户端](https://github.com/wildfirechat/ios-chat)进行验证。详情可参考[快速开始](https://docs.wildfirechat.cn/quick_start/)。
|
||||
|
||||
## 打包RPM格式
|
||||
打包会生成Java包和deb安装包,如果需要rpm安装包,请在```distribution/pom.xml```中取消注释生成rpm包的plugin。另外还需要本地安装有rpm,在linux或者mac系统中很容易安装,在windows系统需要安装cygwin并安装rpm,具体信息请百度查询。
|
||||
|
||||
修改之后运行编译命令```mvn clean package```,rpm包生成在```distribution/target```目录下。
|
||||
|
||||
## 升级说明
|
||||
1. 从0.42 版本增加了群成员数限制,默认为2000。如果您从之前的版本升级到这个版本或以后,需要注意到群成员数的限制。升级之后超出限制的群不受影响,但不能继续加人,如果您想修改默认值,可以在升级版本之后,修改t_setting表,把默认的大小改为您期望的人数。另外修改t_group表,把已经存在的群组max_member_count改成您期望的,然后重启。
|
||||
2. 0.50版本添加了是否允许客户端发送群操作通知的配置。如果您在客户端自定义群通知,需要在服务器端配置允许,没有使用自定义群操作通知的不受影响。***
|
||||
@@ -131,23 +128,104 @@ mvn clean package
|
||||
9. 从0.79 版本起把log4j升级到log4j2,因为log4j已经不再维护而且还有已知的漏洞,建议所有客户都升级,升级时注意更新log4j2的配置文件
|
||||
10. 0.97版本更改了启动脚本```wildfirechat.sh```,如果是升级服务,请注意更新启动脚本。
|
||||
|
||||
## 应用截图
|
||||
登录界面
|
||||
|
||||
## 联系我们
|
||||
<img src="./screenshots/1_login.png" width = 50% height = 50% />
|
||||
|
||||
商务合作请微信联系:
|
||||
会话列表
|
||||
|
||||
* 微信1:wildfirechat
|
||||
* 微信2:wfchat
|
||||
<img src="./screenshots/2_conversation_list.png" width = 50% height = 50% />
|
||||
|
||||
## 问题交流
|
||||
好友列表
|
||||
|
||||
1. 如果大家发现bug,请在GitHub或码云提issue;如果有需求也请给我们提issue。
|
||||
2. 其他问题,请到[野火IM论坛](http://bbs.wildfirechat.cn/)进行交流学习
|
||||
3. 关注我们的公众号。我们有新版本发布或者有重大更新会通过公众号通知大家,另外我们也会不定期的发布一些关于野火IM的技术介绍。
|
||||
<img src="./screenshots/3_contacts_list.png" width = 50% height = 50% />
|
||||
|
||||
<img src="http://static.wildfirechat.cn/wx_wfc_qrcode.jpg" width = 50% height = 50% />
|
||||
工作台
|
||||
|
||||
我们有核心研发工程师轮流值班处理issue和论坛,会及时处理的,疑难Bug的修改和新需求的开发我们也会尽快解决。
|
||||
<img src="./screenshots/4_workplatform.png" width = 50% height = 50% />
|
||||
|
||||
发现
|
||||
|
||||
<img src="./screenshots/5_discover.png" width = 50% height = 50% />
|
||||
|
||||
我的页面
|
||||
|
||||
<img src="./screenshots/6_settings.png" width = 50% height = 50% />
|
||||
|
||||
消息聊天
|
||||
|
||||
<img src="./screenshots/7_conversation.png" width = 50% height = 50% />
|
||||
|
||||
动态表情
|
||||
|
||||
<img src="./screenshots/8_conversation_sticker.png" width = 50% height = 50% />
|
||||
|
||||
语音消息
|
||||
|
||||
<img src="./screenshots/9_conversation_voice_msg.png" width = 50% height = 50% />
|
||||
|
||||
位置消息
|
||||
|
||||
<img src="./screenshots/10_conversation_location.png" width = 50% height = 50% />
|
||||
|
||||
拍摄图片或者小视频
|
||||
|
||||
<img src="./screenshots/11_conversation_capture.jpeg" width = 50% height = 50% />
|
||||
|
||||
会话设置
|
||||
|
||||
<img src="./screenshots/13_conversation_settings.png" width = 50% height = 50% />
|
||||
|
||||
朋友圈
|
||||
|
||||
<img src="./screenshots/14_moments.png" width = 50% height = 50% />
|
||||
|
||||
新好友
|
||||
|
||||
<img src="./screenshots/15_new_friends.png" width = 50% height = 50% />
|
||||
|
||||
多人视频通话
|
||||
|
||||
<img src="./screenshots/16_videocall.png" width = 50% height = 50% />
|
||||
|
||||
会议主页
|
||||
|
||||
<img src="./screenshots/17_conference_home.png" width = 50% height = 50% />
|
||||
|
||||
会议详情
|
||||
|
||||
<img src="./screenshots/18_conference_info.png" width = 50% height = 50% />
|
||||
|
||||
会议界面
|
||||
|
||||
<img src="./screenshots/19_conference.png" width = 50% height = 50% />
|
||||
|
||||
PC客户端界面
|
||||
|
||||
<img src="./screenshots/20_pc.png"/>
|
||||
|
||||
移动客户端、PC客户端和Web客户端三端同框
|
||||
|
||||
<img src="./screenshots/21_three_platform.png" />
|
||||
|
||||
小程序客户端
|
||||
|
||||
<img src="./screenshots/22_micro_app.jpeg" width = 50% height = 50% />
|
||||
|
||||
公众号管理后台
|
||||
|
||||
<img src="./screenshots/23_channel.png"/>
|
||||
|
||||
开放平台管理后台
|
||||
|
||||
<img src="./screenshots/24_open_platform.png" />
|
||||
|
||||
IM服务管理后台
|
||||
|
||||
<img src="./screenshots/25_im_admin.png" />
|
||||
|
||||
> 更多详细信息请下载demo进行体验。
|
||||
|
||||
## 特别感谢
|
||||
1. [moquette](https://github.com/moquette-io/moquette) 本项目是基于此项目二次开发而来,处理MQTT相关业务。
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#服务器的接入IP。给客户端提供是${server.ip}和${http_port}。
|
||||
#客户端会从${http_port}端口获取到长链接端口。这个地址一定要改成客户端可以访问到的IP地址
|
||||
#(如果您部署云服务器上或者具有独立公网出口的服务器上,请改为对应的公网IP;如果您部署在在内网环境下,在内网使用,这个地方改成内网地址)
|
||||
server.ip 192.168.3.124
|
||||
server.ip 192.168.1.81
|
||||
|
||||
##原生客户端长链接端口
|
||||
port 1883
|
||||
@@ -59,6 +59,15 @@ token.key testim
|
||||
##token的过期时间,单位为毫秒,默认为无限期。如果需要设置无限期,客户端上一定需要加上token过期的处理。token过期的处理请参考文档的常见问题
|
||||
##token.expire_time 2592000000
|
||||
|
||||
##客户端(目前只有android)的应用签名(一个应用最取第一个签名),如果有多个签名(多个客户端),用英文逗号分开。获取签名方法请参考文档:https://docs.wildfirechat.cn/blogs/签名验证.html
|
||||
#connect.client_signature_list eNkezQ1g9OsnhfLSFUY1vzKDzhs=,xykezQ1g9OsnhfLSFUY1vzKDzhs=
|
||||
|
||||
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
|
||||
#connect.reject_empty_signature true
|
||||
|
||||
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
|
||||
#encrypt.use_aes256 true
|
||||
|
||||
##首次登录,是否接收之前的历史消息。
|
||||
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
|
||||
##1接收,会接收 message.max_queue 配置的条数的历史消息
|
||||
@@ -79,6 +88,9 @@ message.chatroom_remote_history_message 1
|
||||
##是否禁止陌生人聊天
|
||||
message.disable_stranger_chat false
|
||||
|
||||
##当禁止陌生人聊天时,允许聊天的用户id,比如管理员或者文件传输助手等。用户id以英文逗号分割。
|
||||
message.allow_stranger_chat_list admin,FireRobot,wfc_file_transfer
|
||||
|
||||
##黑名单策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃
|
||||
message.blacklist.strategy 0
|
||||
|
||||
@@ -142,6 +154,9 @@ friend.reject_request_duration 2592000000
|
||||
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
|
||||
friend.request_expiration_duration 604800000
|
||||
|
||||
##请求添加机器人为好友时,机器人是否自动接受,默认为true
|
||||
friend.robot_auto_accept true
|
||||
|
||||
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
|
||||
chatroom.participant_idle_time 900000
|
||||
|
||||
@@ -161,6 +176,10 @@ group.allow_robot_custom_operation_notification true
|
||||
## 0 不发送,1 退群时发送,2 踢人时发送,3 退群和踢人时都发送。
|
||||
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信息。当需要隐藏多个时以英文逗号分开;
|
||||
## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。
|
||||
## 注意,修改本配置不会对已经同步的信息产生影响。
|
||||
@@ -293,17 +312,23 @@ push.ios.server.address http://localhost:8085/ios/push
|
||||
##消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.forward.url http://localhost:8888/im_event/message
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割,可以用-来指定区间,注意区间不能太大,因为要把区间内的所有数字都放入到Set中。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3,5-10
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割,可以用-来指定区间,注意区间不能太大,因为要把区间内的所有数字都放入到Set中。
|
||||
#message.forward.exclude_types 1,2,3,5-10
|
||||
|
||||
##敏感消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.sensitive.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。
|
||||
##此转发不受${message.forward.types}和${message.forward.exclude_types}限制。
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.mentionmsg.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
##撤回消息转发地址,当用户撤回消息会回调此地址。
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.recallmsg.forward.url http://localhost:8888/im_event/recall_message
|
||||
|
||||
##设备信息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
alter table `t_group_member` add INDEX `group_member_mid_index` (`_mid`);
|
||||
@@ -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)
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
alter table `t_group_member` add INDEX `group_member_mid_index` (`_mid`);
|
||||
@@ -5,7 +5,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.97</version>
|
||||
<version>1.1.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>moquette-broker</artifactId>
|
||||
|
||||
@@ -12,9 +12,11 @@ package cn.wildfirechat.push;
|
||||
public class PushMessage {
|
||||
public String sender;
|
||||
public String senderName;
|
||||
public String senderPortrait;
|
||||
public int convType;
|
||||
public String target;
|
||||
public String targetName;
|
||||
public String targetPortrait;
|
||||
public String userId;
|
||||
public int line;
|
||||
public int cntType;
|
||||
@@ -34,12 +36,14 @@ public class PushMessage {
|
||||
public String language;
|
||||
public long messageId;
|
||||
|
||||
public PushMessage(String sender, int conversationType, String target, int line, int messageContentType, long serverTime, String senderName, String targetName, int unReceivedMsg, int mentionedType, boolean isHiddenDetail, String language) {
|
||||
public PushMessage(String sender, int conversationType, String target, int line, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionedType, boolean isHiddenDetail, String language) {
|
||||
this.sender = sender;
|
||||
this.convType = conversationType;
|
||||
this.target = target;
|
||||
this.senderName = senderName;
|
||||
this.senderPortrait = senderPortrait;
|
||||
this.targetName = targetName;
|
||||
this.targetPortrait = targetPortrait;
|
||||
this.line = line;
|
||||
this.cntType = messageContentType;
|
||||
this.serverTime = serverTime;
|
||||
|
||||
@@ -90,6 +90,8 @@ public class FileAction extends Action {
|
||||
}
|
||||
|
||||
response.setContent(file);
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,11 @@ public class IMAction extends Action {
|
||||
if (userId == null) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null);
|
||||
} 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() {
|
||||
@Override
|
||||
public void onSuccess(byte[] result) {
|
||||
|
||||
@@ -39,17 +39,10 @@ public class RouteAction extends Action {
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
|
||||
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());
|
||||
|
||||
@@ -57,15 +50,20 @@ public class RouteAction extends Action {
|
||||
try {
|
||||
bytes = Base64.getDecoder().decode(str);
|
||||
} catch (IllegalArgumentException e) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
String cid = fullHttpRequest.headers().get("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) {
|
||||
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;
|
||||
}
|
||||
cid = new String(cbytes);
|
||||
@@ -74,7 +72,7 @@ public class RouteAction extends Action {
|
||||
byte[] ubytes = Base64.getDecoder().decode(uid);
|
||||
ubytes = AES.AESDecrypt(ubytes, "", true);
|
||||
if (ubytes == null) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
|
||||
return true;
|
||||
}
|
||||
uid = new String(ubytes);
|
||||
@@ -84,7 +82,7 @@ public class RouteAction extends Action {
|
||||
if (session == null) {
|
||||
ErrorCode errorCode = sessionsStore.loadActiveSession(uid, cid);
|
||||
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
sendResponse(response, errorCode, null, base64Response);
|
||||
sendResponse(response, errorCode, null);
|
||||
return true;
|
||||
}
|
||||
session = sessionsStore.sessionForClientAndUser(uid, cid);
|
||||
@@ -94,16 +92,20 @@ public class RouteAction extends Action {
|
||||
if (session != null) {
|
||||
bytes = AES.AESDecrypt(bytes, session.getSecret(), true);
|
||||
} else {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (bytes == null) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(messagesStore.getUserStatus(uid) == ProtoConstants.UserStatus.Forbidden) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_USER_BLOCKED, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
WFCMessage.IMHttpWrapper wrapper = WFCMessage.IMHttpWrapper.parseFrom(bytes);
|
||||
@@ -111,22 +113,22 @@ public class RouteAction extends Action {
|
||||
String userId = Tokenor.getUserId(token.getBytes());
|
||||
LOG.info("RouteAction token={}, userId={}", token, userId);
|
||||
if (userId == null) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null);
|
||||
} else {
|
||||
ServerAPIHelper.sendRequest(userId, wrapper.getClientId(), wrapper.getRequest(), wrapper.getData().toByteArray(), new ServerAPIHelper.Callback() {
|
||||
@Override
|
||||
public void onSuccess(byte[] result) {
|
||||
sendResponse(response, null, result, base64Response);
|
||||
sendResponse(response, null, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorCode errorCode) {
|
||||
sendResponse(response, errorCode, null, base64Response);
|
||||
sendResponse(response, errorCode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout() {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null, base64Response);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,25 +141,21 @@ public class RouteAction extends Action {
|
||||
return false;
|
||||
}
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, false);
|
||||
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (contents == null) {
|
||||
ByteBuf ackPayload = Unpooled.buffer();
|
||||
ackPayload.ensureWritable(1).writeByte(errorCode.getCode());
|
||||
contents = ackPayload.array();
|
||||
}
|
||||
if (base64Response) {
|
||||
byte[] base64Data = Base64.getEncoder().encode(contents);
|
||||
response.setContent(base64Data);
|
||||
} else {
|
||||
response.setContent(contents);
|
||||
}
|
||||
|
||||
response.setContent(contents);
|
||||
response.send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +187,10 @@ public class UploadFileAction extends Action {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(remoteFileName != null && remoteFileName.length() > 2 && remoteFileName.startsWith("'") && remoteFileName.endsWith("'")) {
|
||||
remoteFileName = remoteFileName.substring(1, remoteFileName.length()-1);
|
||||
}
|
||||
|
||||
if (StringUtil.isNullOrEmpty(remoteFileName)) {
|
||||
logger.warn("remoteFileName is empty!");
|
||||
|
||||
@@ -235,12 +239,17 @@ public class UploadFileAction extends Action {
|
||||
int offset = 0; // 断点续传开始位置
|
||||
|
||||
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);
|
||||
|
||||
datePath = "fs/" + bucket[0] + "/" + datePath; //add bucket
|
||||
|
||||
String dir = "./" + MediaServerConfig.FILE_STROAGE_ROOT + "/" + datePath;
|
||||
String dir;
|
||||
if(MediaServerConfig.FILE_STROAGE_ROOT.startsWith("/") || MediaServerConfig.FILE_STROAGE_ROOT.startsWith("~/") || MediaServerConfig.FILE_STROAGE_ROOT.startsWith("./")) {
|
||||
dir = MediaServerConfig.FILE_STROAGE_ROOT + "/" + datePath;
|
||||
} else {
|
||||
dir = "./" + MediaServerConfig.FILE_STROAGE_ROOT + "/" + datePath;
|
||||
}
|
||||
|
||||
File dirFile = new File(dir);
|
||||
boolean bFile = dirFile.exists();
|
||||
@@ -248,6 +257,7 @@ public class UploadFileAction extends Action {
|
||||
if(!bFile) {
|
||||
bFile = dirFile.mkdirs();
|
||||
if (!bFile) {
|
||||
logger.error("create dirs error! {}", dir);
|
||||
response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
|
||||
response.setContent("服务器错误:无法创建文件");
|
||||
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,55 @@
|
||||
/*
|
||||
* 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.InputUserId;
|
||||
import cn.wildfirechat.pojos.OutputGroupIds;
|
||||
import cn.wildfirechat.pojos.StringPairPojo;
|
||||
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.Set;
|
||||
|
||||
@Route(APIPath.Get_Common_Groups)
|
||||
@HttpMethod("POST")
|
||||
public class GetCommonGroupsAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
StringPairPojo input = getRequestBody(request.getNettyRequest(), StringPairPojo.class);
|
||||
if (input != null
|
||||
&& (!StringUtil.isNullOrEmpty(input.getFirst())) && (!StringUtil.isNullOrEmpty(input.getSecond()))) {
|
||||
|
||||
Set<String> groupIds = messagesStore.getCommonGroupIds(input.getFirst(), input.getSecond());
|
||||
OutputGroupIds outputGroupIds = new OutputGroupIds();
|
||||
outputGroupIds.setGroupIds(new ArrayList<>(groupIds));
|
||||
RestResult result = RestResult.ok(outputGroupIds);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class GetUserAction extends AdminAction {
|
||||
}
|
||||
|
||||
RestResult result;
|
||||
if (user == null) {
|
||||
if (user == null || user.getDeleted() > 0) {
|
||||
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
|
||||
} else {
|
||||
result = RestResult.ok(InputOutputUserInfo.fromPbUser(user));
|
||||
|
||||
@@ -25,6 +25,9 @@ import io.netty.util.internal.StringUtil;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Route(APIPath.Msg_Recall)
|
||||
@HttpMethod("POST")
|
||||
public class RecallMessageAction extends AdminAction {
|
||||
@@ -42,10 +45,9 @@ public class RecallMessageAction extends AdminAction {
|
||||
|
||||
WFCMessage.INT64Buf idBuf = WFCMessage.INT64Buf.newBuilder().setId(recallMessageData.getMessageUid()).build();
|
||||
sendApiMessage(response, recallMessageData.getOperator(), IMTopic.RecallMessageTopic, idBuf.toByteArray(), result -> {
|
||||
ByteBuf byteBuf = Unpooled.buffer();
|
||||
byteBuf.writeBytes(result);
|
||||
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
|
||||
return new Result(errorCode);
|
||||
ErrorCode errorCode = ErrorCode.fromCode(result[0]);
|
||||
byte[] data = Arrays.copyOfRange(result,1, result.length);
|
||||
return new Result(errorCode, new String(data, StandardCharsets.UTF_8));
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class GetUserAction extends ChannelAction {
|
||||
|
||||
RestResult result;
|
||||
|
||||
if (user == null || StringUtil.isNullOrEmpty(user.getName())) {
|
||||
if (user == null || StringUtil.isNullOrEmpty(user.getName()) || user.getDeleted() > 0) {
|
||||
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
|
||||
} else {
|
||||
if (channelInfo.getOwner().equals(inputUserId.getUserId()) ||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class GetUserAction extends RobotAction {
|
||||
}
|
||||
|
||||
RestResult result;
|
||||
if (user == null) {
|
||||
if (user == null || user.getDeleted() > 0) {
|
||||
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
|
||||
} else {
|
||||
result = RestResult.ok(InputOutputUserInfo.fromPbUser(user));
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import win.liyufan.im.Utility;
|
||||
@@ -34,7 +35,6 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
|
||||
Logger.info("Http request whit url {}", fullHttpRequest.uri());
|
||||
final Request request = Request.build(ctx, fullHttpRequest);
|
||||
final Response response = Response.build(ctx, request);
|
||||
|
||||
@@ -109,7 +109,7 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
|
||||
* @param 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())){
|
||||
handleOptions(ctx, request, response);
|
||||
return;
|
||||
@@ -124,6 +124,9 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
|
||||
Action action;
|
||||
if (isValidePath(request.getPath())) {
|
||||
action = ServerSetting.getAction(request.getPath(), request.getMethod().toUpperCase());
|
||||
if (action != null) {
|
||||
Logger.info("Http request whit url {}", request.getPath());
|
||||
}
|
||||
} else {
|
||||
action = ServerSetting.getErrorAction(ServerSetting.MAPPING_ERROR);
|
||||
}
|
||||
@@ -137,7 +140,11 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
|
||||
action = ServerSetting.getAction(ServerSetting.MAPPING_ALL, request.getMethod());
|
||||
if(null == action){
|
||||
// 非Action方法,调用静态文件读取
|
||||
action = Singleton.get(FileAction.class);
|
||||
if(request.getPath().startsWith("/fs")) {
|
||||
action = Singleton.get(FileAction.class);
|
||||
} else {
|
||||
action = ServerSetting.getErrorAction(ServerSetting.MAPPING_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
action.ctx = ctx;
|
||||
|
||||
@@ -29,6 +29,8 @@ public final class BrokerConstants {
|
||||
public static final String HTTP_SERVER_PORT = "http_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 DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb";
|
||||
public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator
|
||||
@@ -110,6 +112,9 @@ public final class BrokerConstants {
|
||||
public static final String TOKEN_SECRET_KEY = "token.key";
|
||||
public static final String TOKEN_EXPIRE_TIME = "token.expire_time";
|
||||
|
||||
public static final String CONNECT_CLIENT_SIGNATURE_LIST = "connect.client_signature_list";
|
||||
public static final String CONNECT_REJECT_EMPTY_SIGNATURE = "connect.reject_empty_signature";
|
||||
|
||||
public static final String EMBED_DB_PROPERTY_NAME = "embed.db";
|
||||
public static final String DB_AUTO_CLEAN_HISTORY_MESSAGES = "db.auto_clean_history_messages";
|
||||
public static final String H2DB_PATH = "h2db.path";
|
||||
@@ -124,8 +129,9 @@ public final class BrokerConstants {
|
||||
public static final String MESSAGE_Forward_Url = "message.forward.url";
|
||||
public static final String MESSAGE_Sensitive_Forward_Url = "message.sensitive.forward.url";
|
||||
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_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_PC_ENDPOINT = "server.multi_pc_endpoint";
|
||||
@@ -141,6 +147,7 @@ public final class BrokerConstants {
|
||||
public static final String MESSAGE_Max_Queue = "message.max_queue";
|
||||
|
||||
public static final String MESSAGE_Disable_Stranger_Chat = "message.disable_stranger_chat";
|
||||
public static final String MESSAGE_Allow_Stranger_Chat_List = "message.allow_stranger_chat_list";
|
||||
|
||||
public static final String MESSAGE_Blacklist_Strategy = "message.blacklist.strategy";
|
||||
|
||||
@@ -156,6 +163,8 @@ public final class BrokerConstants {
|
||||
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_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_Rejoin_When_Active = "chatroom.rejoin_when_active";
|
||||
@@ -166,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_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_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) {
|
||||
publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, request.getTargetUid(), head[0], fromUser, request.getReason());
|
||||
} else if(user != null && user.getType() == ProtoConstants.UserType.UserType_Robot) {
|
||||
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);
|
||||
if(m_messagesStore.isRobotAutoAcceptFriendRequest()) {
|
||||
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;
|
||||
|
||||
@@ -24,6 +24,20 @@ public class AddGroupMember extends GroupHandler<WFCMessage.AddGroupMemberReques
|
||||
@Override
|
||||
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;
|
||||
|
||||
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());
|
||||
if (errorCode == ERROR_CODE_SUCCESS) {
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.moquette.imhandler;
|
||||
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Handler(IMTopic.ListenedChannelListTopic)
|
||||
public class ChannelListenedListHandler extends IMHandler<Void> {
|
||||
@Override
|
||||
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, Void request, Qos1PublishHandler.IMCallback callback) {
|
||||
List<String> channelInfoList = m_messagesStore.getListenedChannels(fromUser);
|
||||
WFCMessage.IDListBuf.Builder builder = WFCMessage.IDListBuf.newBuilder();
|
||||
builder.addAllId(channelInfoList);
|
||||
byte[] data = builder.build().toByteArray();
|
||||
ackPayload.ensureWritable(data.length).writeBytes(data);
|
||||
return ErrorCode.ERROR_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import win.liyufan.im.IMTopic;
|
||||
public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupRequest> {
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,16 @@ public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupReque
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
if(!isAdmin && request.getGroup().getGroupInfo().getType() == ProtoConstants.GroupType.GroupType_Organization) {
|
||||
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);
|
||||
if (groupInfo != null) {
|
||||
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
|
||||
@@ -26,7 +26,6 @@ public class DismissGroupHandler extends GroupHandler<WFCMessage.DismissGroupReq
|
||||
ErrorCode errorCode;
|
||||
if (groupInfo == null) {
|
||||
errorCode = m_messagesStore.dismissGroup(fromUser, request.getGroupId(), isAdmin);
|
||||
|
||||
} else if (isAdmin || (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted)
|
||||
&& groupInfo.getOwner() != null && groupInfo.getOwner().equals(fromUser)) {
|
||||
|
||||
@@ -38,6 +37,13 @@ public class DismissGroupHandler extends GroupHandler<WFCMessage.DismissGroupReq
|
||||
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
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package io.moquette.imhandler;
|
||||
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
|
||||
|
||||
@Handler(IMTopic.GetCommonGroupsTopic)
|
||||
public class GetCommonGroupsHandler extends IMHandler<WFCMessage.IDBuf> {
|
||||
@Override
|
||||
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.IDBuf request, Qos1PublishHandler.IMCallback callback) {
|
||||
WFCMessage.PullUserResult.Builder resultBuilder = WFCMessage.PullUserResult.newBuilder();
|
||||
Set<String> strings = m_messagesStore.getCommonGroupIds(fromUser, request.getId());
|
||||
WFCMessage.IDListBuf idListBuf = WFCMessage.IDListBuf.newBuilder().addAllId(strings).build();
|
||||
byte[] data = idListBuf.toByteArray();
|
||||
ackPayload.ensureWritable(data.length).writeBytes(data);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
public class GetGroupInfoHandler extends IMHandler<WFCMessage.PullUserRequest> {
|
||||
@Override
|
||||
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();
|
||||
byte[] data = result.toByteArray();
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package io.moquette.imhandler;
|
||||
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
|
||||
|
||||
@Handler(IMTopic.GetMyGroupsTopic)
|
||||
public class GetMyGroupsHandler extends IMHandler<Void> {
|
||||
@Override
|
||||
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, Void request, Qos1PublishHandler.IMCallback callback) {
|
||||
WFCMessage.PullUserResult.Builder resultBuilder = WFCMessage.PullUserResult.newBuilder();
|
||||
Set<String> strings = m_messagesStore.getUserGroupIds(fromUser);
|
||||
WFCMessage.IDListBuf idListBuf = WFCMessage.IDListBuf.newBuilder().addAllId(strings).build();
|
||||
byte[] data = idListBuf.toByteArray();
|
||||
ackPayload.ensureWritable(data.length).writeBytes(data);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,10 @@ public class KickoffGroupMember extends GroupHandler<WFCMessage.RemoveGroupMembe
|
||||
errorCode = ErrorCode.ERROR_CODE_NOT_EXIST;
|
||||
} else {
|
||||
boolean isAdmin = requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin;
|
||||
if (!isAdmin && groupInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
boolean isAllow = isAdmin;
|
||||
if (!isAllow) {
|
||||
if (groupInfo.getOwner() != null) {
|
||||
@@ -58,6 +62,13 @@ public class KickoffGroupMember extends GroupHandler<WFCMessage.RemoveGroupMembe
|
||||
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
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (errorCode == ERROR_CODE_SUCCESS) {
|
||||
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
|
||||
@@ -31,7 +31,14 @@ public class QuitGroupHandler extends GroupHandler<WFCMessage.QuitGroupRequest>
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
ErrorCode errorCode = m_messagesStore.quitGroup(fromUser, request.getGroupId());
|
||||
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);
|
||||
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
|
||||
|
||||
@@ -23,7 +23,7 @@ public class RecallMessageHandler extends IMHandler<WFCMessage.INT64Buf> {
|
||||
@Override
|
||||
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.INT64Buf int64Buf, Qos1PublishHandler.IMCallback callback) {
|
||||
boolean isAdmin = requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin;
|
||||
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, clientID, isAdmin);
|
||||
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, clientID, isAdmin, ackPayload);
|
||||
|
||||
if(errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
return errorCode;
|
||||
|
||||
@@ -40,6 +40,11 @@ public class RouteHandler extends IMHandler<WFCMessage.RouteRequest> {
|
||||
return ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH;
|
||||
}
|
||||
|
||||
if(request.getPlatform() != session.getPlatform() && m_messagesStore.existSignatures()) {
|
||||
LOG.error("Session <{}, {}> platform is {} mismatch the request {}", session.getUsername(), session.getClientID(), session.getPlatform(), request.getPlatform());
|
||||
return ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH;
|
||||
}
|
||||
|
||||
String serverIp = mServer.getServerIp();
|
||||
String longPort = mServer.getLongPort();
|
||||
String shortPort = mServer.getShortPort();
|
||||
|
||||
@@ -22,6 +22,7 @@ import cn.wildfirechat.common.ErrorCode;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import win.liyufan.im.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
private String mForwardUrl = null;
|
||||
private String mSensitiveMessageForwardUrl = null;
|
||||
private Set<Integer> mForwardMessageTypes = new HashSet<>();
|
||||
private Set<Integer> mForwardExcludeMessageTypes = new HashSet<>();
|
||||
private String mMentionForwardUrl = null;
|
||||
private int mBlacklistStrategy = 0; //黑名单中时,0失败,1吞掉。
|
||||
private boolean mNoForwardAdminMessage = false;
|
||||
@@ -47,12 +49,9 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
mForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Url);
|
||||
if (!StringUtil.isNullOrEmpty(mForwardUrl)) {
|
||||
String forwardTypes = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Types);
|
||||
if (!StringUtil.isNullOrEmpty(forwardTypes)) {
|
||||
String[] tss = forwardTypes.split(",");
|
||||
for (String ts:tss) {
|
||||
mForwardMessageTypes.add(Integer.parseInt(ts.trim()));
|
||||
}
|
||||
}
|
||||
parseTypes(mForwardMessageTypes, forwardTypes);
|
||||
String excludeTypes = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Exclude_Types);
|
||||
parseTypes(mForwardExcludeMessageTypes, excludeTypes);
|
||||
}
|
||||
mSensitiveMessageForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Sensitive_Forward_Url);
|
||||
mMentionForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_MentionMsg_Forward_Url);
|
||||
@@ -97,6 +96,30 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
|
||||
}
|
||||
|
||||
private void parseTypes(Collection<Integer> collection, String types) {
|
||||
try {
|
||||
if (!StringUtil.isNullOrEmpty(types)) {
|
||||
String[] tss = types.split(",");
|
||||
for (String ts:tss) {
|
||||
if(ts.contains("-")) {
|
||||
String[] ss = ts.split("-");
|
||||
if(ss.length == 2) {
|
||||
int begin = Integer.parseInt(ss[0]);
|
||||
int end = Integer.parseInt(ss[1]);
|
||||
for (int i = begin; i <= end ; i++) {
|
||||
collection.add(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
collection.add(Integer.parseInt(ts.trim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.Message message, Qos1PublishHandler.IMCallback callback) {
|
||||
ErrorCode errorCode = ErrorCode.ERROR_CODE_SUCCESS;
|
||||
@@ -159,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();
|
||||
@@ -179,7 +211,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
}
|
||||
}
|
||||
|
||||
if (!StringUtil.isNullOrEmpty(mForwardUrl) && (mForwardMessageTypes.isEmpty() || mForwardMessageTypes.contains(message.getContent().getType())) && !(isAdmin && mNoForwardAdminMessage)) {
|
||||
if (!StringUtil.isNullOrEmpty(mForwardUrl) && (mForwardMessageTypes.isEmpty() || mForwardMessageTypes.contains(message.getContent().getType())) && !(isAdmin && mNoForwardAdminMessage) && !mForwardExcludeMessageTypes.contains(message.getContent().getType())) {
|
||||
publisher.forwardMessage(message, mForwardUrl, outputClient);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,13 @@ public class SetGroupManagerHandler extends GroupHandler<WFCMessage.SetGroupMana
|
||||
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);
|
||||
if (errorCode == ERROR_CODE_SUCCESS) {
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
|
||||
@@ -30,6 +30,13 @@ public class TransferGroupHandler extends GroupHandler<WFCMessage.TransferGroupR
|
||||
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);
|
||||
if (errorCode == ERROR_CODE_SUCCESS) {
|
||||
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
|
||||
|
||||
@@ -25,9 +25,11 @@ public class UploadDeviceTokenHandler extends IMHandler<WFCMessage.UploadDeviceT
|
||||
session.setPlatform(request.getPlatform());
|
||||
session.setAppName(request.getAppName());
|
||||
if (request.getPlatform() == ProtoConstants.Platform.Platform_iOS && request.getPushType() == 2) {
|
||||
LOG.info("Set device token, userId {}", fromUser);
|
||||
session.setVoipDeviceToken(request.getDeviceToken());
|
||||
m_sessionsStore.updateSessionToken(session, true);
|
||||
} else {
|
||||
LOG.info("Set device token, userId {}, platform {}, pushType {}", fromUser, session.getPlatform(), request.getPushType());
|
||||
session.setDeviceToken(request.getDeviceToken());
|
||||
session.setPushType(request.getPushType());
|
||||
m_sessionsStore.updateSessionToken(session, false);
|
||||
|
||||
@@ -39,6 +39,7 @@ import static cn.wildfirechat.common.IMExceptionEvent.EventType.RDBS_Exception;
|
||||
import static cn.wildfirechat.proto.ProtoConstants.PersistFlag.Transparent;
|
||||
import static io.moquette.server.Constants.MAX_MESSAGE_QUEUE;
|
||||
import static cn.wildfirechat.proto.ProtoConstants.SearchUserType.*;
|
||||
import static win.liyufan.im.UserSettingScope.kUserSettingPrivacySearchable;
|
||||
|
||||
public class DatabaseStore {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DatabaseStore.class);
|
||||
@@ -161,18 +162,12 @@ public class DatabaseStore {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//searchType
|
||||
// 0 模糊匹配displayName, 精确匹配账户名和电话号码
|
||||
// 1 精确匹配账户名和电话号码
|
||||
// 2 精确匹配账户名
|
||||
// 3 精确匹配电话号码
|
||||
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
|
||||
|
||||
List<WFCMessage.User> searchUserByNameMobile(String keyword, int searchType) {
|
||||
ArrayList<WFCMessage.User> out = new ArrayList<>();
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
ArrayList<WFCMessage.User> out = new ArrayList<>();
|
||||
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql = "select `_uid`, `_name`" +
|
||||
@@ -185,61 +180,34 @@ public class DatabaseStore {
|
||||
", `_company`" +
|
||||
", `_social`" +
|
||||
", `_extra`" +
|
||||
", `_dt` from t_user";
|
||||
switch (searchType) {
|
||||
case SearchUserType_Name_Mobile:
|
||||
sql += " where (`_name` = ? or `_mobile` = ?) ";
|
||||
break;
|
||||
case SearchUserType_Name:
|
||||
sql += " where `_name` = ? ";
|
||||
break;
|
||||
case SearchUserType_Mobile:
|
||||
sql += " where `_mobile` = ? ";
|
||||
break;
|
||||
case SearchUserType_General:
|
||||
default:
|
||||
sql += " where (`_display_name` like ? or `_name` = ? or `_mobile` = ?) ";
|
||||
break;
|
||||
", `_dt`, `_type` from t_user";
|
||||
|
||||
if(searchType == SearchUserType_Name) {
|
||||
sql += " where `_name` = ? ";
|
||||
} else if(searchType == SearchUserType_Mobile) {
|
||||
sql += " where `_mobile` = ? ";
|
||||
} else {
|
||||
sql += " where (`_name` = ? or `_mobile` = ?) ";
|
||||
}
|
||||
|
||||
sql += " and `_type` <> 2 and `_deleted` = 0"; //can search normal user(0) and robot(1) and admin(100), can not search things
|
||||
|
||||
sql += " and _type <> 2"; //can search normal user(0) and robot(1) and admin(100), can not search things
|
||||
|
||||
if (searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
|
||||
if(searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
|
||||
sql += " limit 1";
|
||||
} else {
|
||||
sql += " limit 20";
|
||||
}
|
||||
|
||||
if (page > 0) {
|
||||
sql += " offset " + page * 20;
|
||||
sql += " limit 2";
|
||||
}
|
||||
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
|
||||
switch (searchType) {
|
||||
case SearchUserType_Name_Mobile:
|
||||
statement.setString(index++, keyword);
|
||||
statement.setString(index++, keyword);
|
||||
break;
|
||||
case SearchUserType_Name:
|
||||
case SearchUserType_Mobile:
|
||||
statement.setString(index++, keyword);
|
||||
break;
|
||||
case SearchUserType_General:
|
||||
default:
|
||||
statement.setString(index++, "%" + keyword + "%");
|
||||
statement.setString(index++, keyword);
|
||||
statement.setString(index++, keyword);
|
||||
break;
|
||||
statement.setString(1, keyword);
|
||||
if(searchType != SearchUserType_Name && searchType != SearchUserType_Mobile) {
|
||||
statement.setString(2, keyword);
|
||||
}
|
||||
|
||||
|
||||
rs = statement.executeQuery();
|
||||
while (rs.next()) {
|
||||
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
|
||||
index = 1;
|
||||
int index = 1;
|
||||
|
||||
String value = rs.getString(index++);
|
||||
value = (value == null ? "" : value);
|
||||
@@ -287,6 +255,9 @@ public class DatabaseStore {
|
||||
long longValue = rs.getLong(index++);
|
||||
builder.setUpdateDt(longValue);
|
||||
|
||||
int type = rs.getInt(index++);
|
||||
builder.setType( type);
|
||||
|
||||
WFCMessage.User user = builder.build();
|
||||
|
||||
out.add(user);
|
||||
@@ -298,6 +269,171 @@ public class DatabaseStore {
|
||||
} finally {
|
||||
DBUtil.closeDB(connection, statement, rs);
|
||||
}
|
||||
|
||||
List<WFCMessage.User> filter = new ArrayList<>();
|
||||
for (WFCMessage.User user : out) {
|
||||
WFCMessage.UserSettingEntry userSettingEntry = Server.getServer().getStore().messagesStore().getUserSetting(user.getUid(), kUserSettingPrivacySearchable, null);
|
||||
if(userSettingEntry != null) {
|
||||
int value = 0;
|
||||
try {
|
||||
value = StringUtil.isNullOrEmpty(userSettingEntry.getValue())?0:Integer.parseInt(userSettingEntry.getValue());
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
|
||||
if (searchType == SearchUserType_Name) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
} else if(searchType != SearchUserType_Mobile) {
|
||||
if(keyword.equals(user.getName())) {
|
||||
if(!keyword.equals(user.getMobile())) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
} else if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
if (searchType == SearchUserType_Mobile) {
|
||||
filter.add(user);
|
||||
} else if(searchType != SearchUserType_Name) {
|
||||
if(keyword.equals(user.getMobile()) && !keyword.equals(user.getName())) {
|
||||
filter.add(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.removeAll(filter);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
List<WFCMessage.User> searchUserByDisplayName(String keyword, int page, List<WFCMessage.User> nameOrIdMatched) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
ArrayList<WFCMessage.User> out = new ArrayList<>();
|
||||
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql = "select u._uid, u._name, u._display_name, u._portrait, u._mobile, u._gender, u._email, u._address, u._company, u._social, u._extra, u._dt, u._type " +
|
||||
" from t_user u left join (select _uid, _value from t_user_setting where _scope = 27) s on u._uid = s._uid " +
|
||||
" where u._display_name like ? and u._type <> 2 and u._deleted = 0 ";
|
||||
if(nameOrIdMatched.size() == 1) {
|
||||
sql += " and u._uid <> ? and u._name <> ?";
|
||||
} else if(nameOrIdMatched.size() == 2) {
|
||||
sql += " and u._uid <> ? and u._uid <>? and u._name <> ? and u._name <>? ";
|
||||
}
|
||||
sql += " and (s._value is null or (s._value <> 1 and s._value <> 3 and s._value <> 5 and s._value <> 7)) limit ";
|
||||
|
||||
if(page == 0) {
|
||||
sql += (20 - nameOrIdMatched.size());
|
||||
} else {
|
||||
sql += 20;
|
||||
}
|
||||
|
||||
if (page > 0) {
|
||||
sql += " offset " + (page * 20 - nameOrIdMatched.size());
|
||||
}
|
||||
|
||||
statement = connection.prepareStatement(sql);
|
||||
statement.setString(1, "%" + keyword + "%");
|
||||
if(nameOrIdMatched.size() == 1) {
|
||||
statement.setString(2, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
|
||||
statement.setString(3, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
|
||||
} else if(nameOrIdMatched.size() == 2) {
|
||||
statement.setString(2, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
|
||||
statement.setString(3, nameOrIdMatched.toArray(new WFCMessage.User[0])[1].getUid());
|
||||
statement.setString(4, nameOrIdMatched.toArray(new WFCMessage.User[0])[0].getUid());
|
||||
statement.setString(5, nameOrIdMatched.toArray(new WFCMessage.User[0])[1].getUid());
|
||||
}
|
||||
|
||||
rs = statement.executeQuery();
|
||||
while (rs.next()) {
|
||||
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
|
||||
int 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);
|
||||
|
||||
long longValue = rs.getLong(index++);
|
||||
builder.setUpdateDt(longValue);
|
||||
|
||||
int type = rs.getInt(index++);
|
||||
builder.setType(type);
|
||||
|
||||
WFCMessage.User user = builder.build();
|
||||
|
||||
out.add(user);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, RDBS_Exception);
|
||||
} finally {
|
||||
DBUtil.closeDB(connection, statement, rs);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
|
||||
List<WFCMessage.User> nameOrIdMatched = searchUserByNameMobile(keyword, searchType);
|
||||
List<WFCMessage.User> out = new ArrayList<>();
|
||||
if(page == 0) {
|
||||
out.addAll(nameOrIdMatched);
|
||||
}
|
||||
|
||||
if(searchType == SearchUserType_General) {
|
||||
List<WFCMessage.User> general = searchUserByDisplayName(keyword, page, nameOrIdMatched);
|
||||
general.removeAll(nameOrIdMatched);
|
||||
out.addAll(general);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -815,7 +951,7 @@ public class DatabaseStore {
|
||||
long beforeUid = before[0];
|
||||
String sql = "select `_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_dt`, `_to` from " + table +" where";
|
||||
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)) {
|
||||
sql += " _type = ? and _line = ? and _mid < ? and _target = ? and ((_from = ? and (_to = '' or _to = ?)) or (_from = ?))";
|
||||
} else {
|
||||
@@ -853,6 +989,7 @@ public class DatabaseStore {
|
||||
statement.setString(index++, user);
|
||||
statement.setString(index++, user);
|
||||
statement.setString(index++, conversation.getTarget());
|
||||
statement.setString(index++, user);
|
||||
} else if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Channel && !user.equals(channelOwner)) {
|
||||
statement.setString(index++, channelOwner);
|
||||
statement.setString(index++, user);
|
||||
@@ -914,7 +1051,7 @@ public class DatabaseStore {
|
||||
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(()->{
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
@@ -929,7 +1066,7 @@ public class DatabaseStore {
|
||||
statement.setString(index++, userId);
|
||||
statement.setLong(index++, messageSeq);
|
||||
statement.setInt(index++, type);
|
||||
statement.setString(index++, target);
|
||||
statement.setString(index++, getPrivateChatUserMessageTarget(type, target, sender));
|
||||
statement.setInt(index++, line);
|
||||
statement.setInt(index++, directing ? 1 :0);
|
||||
statement.setInt(index++, messageContentType);
|
||||
@@ -945,6 +1082,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) {
|
||||
mScheduler.execute(()->{
|
||||
String tableName = getUserMessageTable(userId);
|
||||
@@ -1493,12 +1638,6 @@ public class DatabaseStore {
|
||||
if (!strEqual(session.getAppName(), request.getApp())) {
|
||||
sql += " `_package_name` = ?,";
|
||||
}
|
||||
if (session.getPlatform() != request.getPlatform()) {
|
||||
sql += " `_platform` = ?,";
|
||||
}
|
||||
if (session.getPushType() != request.getPushType()) {
|
||||
sql += " `_push_type` = ?,";
|
||||
}
|
||||
if (!strEqual(session.getDeviceName(), request.getDeviceName())) {
|
||||
sql += " `_device_name` = ?,";
|
||||
}
|
||||
@@ -1526,12 +1665,6 @@ public class DatabaseStore {
|
||||
if (!strEqual(session.getAppName(), 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())) {
|
||||
statement.setString(index++, request.getDeviceName());
|
||||
}
|
||||
@@ -1712,6 +1845,35 @@ public class DatabaseStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> getCommonGroupIds(String userId1, String userId2) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql = "select t1._gid from t_group_member t1, t_group_member t2 where t1._mid = ? and t2._mid = ? and t1._type <> 4 and t2._type <> 4 and t1._gid = t2._gid";
|
||||
statement = connection.prepareStatement(sql);
|
||||
|
||||
statement.setString(1, userId1);
|
||||
statement.setString(2, userId2);
|
||||
|
||||
rs = statement.executeQuery();
|
||||
Set<String> out = new HashSet<>();
|
||||
while (rs.next()) {
|
||||
String uid = rs.getString(1);
|
||||
out.add(uid);
|
||||
}
|
||||
return out;
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, RDBS_Exception);
|
||||
} finally {
|
||||
DBUtil.closeDB(connection, statement, rs);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void updateGroupMemberDt(final String groupId, final long dt) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
@@ -2385,59 +2547,55 @@ public class DatabaseStore {
|
||||
}
|
||||
|
||||
void deleteUserStatus(String userId) {
|
||||
mScheduler.execute(()->{
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
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 = ?";
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void updateUserStatus(String userId, int status) {
|
||||
mScheduler.execute(()->{
|
||||
Connection connection = null;
|
||||
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);
|
||||
}
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, RDBS_Exception);
|
||||
} finally {
|
||||
DBUtil.closeDB(connection, statement);
|
||||
}
|
||||
}
|
||||
|
||||
int getGeneratedId() {
|
||||
@@ -2618,6 +2776,103 @@ public class DatabaseStore {
|
||||
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() {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
@@ -3316,47 +3571,45 @@ public class DatabaseStore {
|
||||
}
|
||||
|
||||
void updateChannelListener(final String channelId, final String listener, final boolean listen) {
|
||||
LOG.info("Database remove channel {}", channelId);
|
||||
mScheduler.execute(()->{
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql;
|
||||
if (listen) {
|
||||
sql = "insert into t_channel_listener (`_cid`" +
|
||||
", `_mid`" +
|
||||
", `_dt`) values(?, ?, ?)" +
|
||||
" ON DUPLICATE KEY UPDATE " +
|
||||
"`_dt` = ?";
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
statement.setString(index++, channelId);
|
||||
statement.setString(index++, listener);
|
||||
statement.setLong(index++, System.currentTimeMillis());
|
||||
statement.setLong(index++, System.currentTimeMillis());
|
||||
LOG.info("updateChannelListener channel {}, listener {}, listen {}", channelId, listener, listen);
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql;
|
||||
if (listen) {
|
||||
sql = "insert into t_channel_listener (`_cid`" +
|
||||
", `_mid`" +
|
||||
", `_dt`) values(?, ?, ?)" +
|
||||
" ON DUPLICATE KEY UPDATE " +
|
||||
"`_dt` = ?";
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
statement.setString(index++, channelId);
|
||||
statement.setString(index++, listener);
|
||||
statement.setLong(index++, System.currentTimeMillis());
|
||||
statement.setLong(index++, System.currentTimeMillis());
|
||||
|
||||
int count = statement.executeUpdate();
|
||||
LOG.info("Update rows {}", count);
|
||||
} else {
|
||||
sql = "delete from t_channel_listener where `_cid`=? and `_mid`=?";
|
||||
int count = statement.executeUpdate();
|
||||
LOG.info("Update rows {}", count);
|
||||
} else {
|
||||
sql = "delete from t_channel_listener where `_cid`=? and `_mid`=?";
|
||||
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
statement.setString(index++, channelId);
|
||||
statement.setString(index++, listener);
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
statement.setString(index++, channelId);
|
||||
statement.setString(index++, listener);
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> getUserChannels(String userId) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import io.moquette.spi.IMessagesStore;
|
||||
import io.moquette.spi.impl.security.AES;
|
||||
import io.moquette.spi.security.Tokenor;
|
||||
import io.moquette.spi.impl.subscriptions.Topic;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.mqtt.MqttVersion;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
@@ -44,11 +45,13 @@ import win.liyufan.im.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -121,6 +124,8 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
private Lock mReadLock = mLock.readLock();
|
||||
private Lock mWriteLock = mLock.writeLock();
|
||||
|
||||
private Lock mUserSettingLock = new ReentrantLock();
|
||||
|
||||
private final DatabaseStore databaseStore;
|
||||
private ConcurrentHashMap<String, Long> userMaxPullSeq = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -138,10 +143,15 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
private long mFriendRequestDuration = 7 * 24 * 60 * 60 * 1000;
|
||||
private long mFriendRejectDuration = 30 * 24 * 60 * 60 * 1000;
|
||||
private long mFriendRequestExpiration = 7 * 24 * 60 * 60 * 1000;
|
||||
private boolean mFriendRobotAutoAccept = true;
|
||||
|
||||
private boolean mMultiPlatformNotification = false;
|
||||
private boolean mMobileDefaultSilentWhenPCOnline = true;
|
||||
private boolean mDisableStrangerChat = false;
|
||||
private Set<String> mAllowStrangerChatSet = new HashSet<>();
|
||||
|
||||
private Set<String> mClientSignatureSet = new HashSet<>();
|
||||
private boolean mRejectEmptySignature = true;
|
||||
|
||||
private long mChatroomParticipantIdleTime = 900000;
|
||||
private boolean mChatroomRejoinWhenActive = true;
|
||||
@@ -164,8 +174,10 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
private boolean mGroupAllowClientCustomOperationNotification;
|
||||
private boolean mGroupAllowRobotCustomOperationNotification;
|
||||
private int mGroupVisibleQuitKickoffNotification;
|
||||
private int mGroupForbiddenClientOperation;
|
||||
private int mSyncDataPartSize = 0;
|
||||
private boolean keepDisplayNameWhenDestroyUser = true;
|
||||
private String mRecallForwardUrl = null;
|
||||
|
||||
private boolean mForwardMessageWithClientInfo = false;
|
||||
private boolean mRobotCallbackWithClientInfo = false;
|
||||
@@ -187,6 +199,27 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
IS_CHATROOM_MESSAGE_REMOTE_HISTORY_MESSAGE = "1".equals(m_Server.getConfig().getProperty(MESSAGE_Remote_Chatroom_History_Message, "1"));
|
||||
Constants.MAX_MESSAGE_QUEUE = Integer.parseInt(m_Server.getConfig().getProperty(MESSAGE_Max_Queue));
|
||||
|
||||
try {
|
||||
String signatureList = m_Server.getConfig().getProperty(BrokerConstants.CONNECT_CLIENT_SIGNATURE_LIST);
|
||||
if(!StringUtil.isNullOrEmptyAfterTrim(signatureList)) {
|
||||
signatureList = signatureList.replace(",", ",");
|
||||
for (String s : signatureList.split(",")) {
|
||||
mClientSignatureSet.add(s.trim());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
if(!mClientSignatureSet.isEmpty()) {
|
||||
mRejectEmptySignature = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CONNECT_REJECT_EMPTY_SIGNATURE, "true"));
|
||||
} else {
|
||||
mRejectEmptySignature = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mDisableStrangerChat = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.MESSAGE_Disable_Stranger_Chat));
|
||||
} catch (Exception e) {
|
||||
@@ -195,6 +228,18 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
printMissConfigLog(MESSAGE_Disable_Stranger_Chat, mDisableStrangerChat + "");
|
||||
}
|
||||
|
||||
try {
|
||||
String allowStrangerList = m_Server.getConfig().getProperty(BrokerConstants.MESSAGE_Allow_Stranger_Chat_List);
|
||||
if(!StringUtil.isNullOrEmptyAfterTrim(allowStrangerList)) {
|
||||
allowStrangerList = allowStrangerList.replace(",", ",");
|
||||
for (String s : allowStrangerList.split(",")) {
|
||||
mAllowStrangerChatSet.add(s.trim());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
mMultiPlatformNotification = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_PLATFROM_NOTIFICATION, "false"));
|
||||
} catch (Exception e) {
|
||||
@@ -255,6 +300,12 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
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 {
|
||||
mChatroomRejoinWhenActive = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Rejoin_When_Active));
|
||||
} catch (Exception e) {
|
||||
@@ -420,6 +471,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 {
|
||||
mSyncDataPartSize = Integer.parseInt(server.getConfig().getProperty(SYNC_Data_Part_Size, "0"));
|
||||
} catch (Exception e) {
|
||||
@@ -462,7 +528,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
try {
|
||||
mRecallForwardUrl = server.getConfig().getProperty(BrokerConstants.MESSAGE_RecallMsg_Forward_Url);
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void printMissConfigLog(String config, String defaultValue) {
|
||||
@@ -529,21 +599,17 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
int pullType = ProtoConstants.PullType.Pull_Normal;
|
||||
|
||||
if (type == ProtoConstants.ConversationType.ConversationType_Private) {
|
||||
notifyReceivers.add(fromUser);
|
||||
if(message.getToCount() > 0) {
|
||||
if(message.getToList().contains(fromUser)) {
|
||||
notifyReceivers.add(fromUser);
|
||||
}
|
||||
if(message.getToList().contains(message.getConversation().getTarget())) {
|
||||
notifyReceivers.add(message.getConversation().getTarget());
|
||||
}
|
||||
} else {
|
||||
notifyReceivers.add(fromUser);
|
||||
notifyReceivers.add(message.getConversation().getTarget());
|
||||
}
|
||||
pullType = ProtoConstants.PullType.Pull_Normal;
|
||||
} else if (type == ProtoConstants.ConversationType.ConversationType_Group) {
|
||||
notifyReceivers.add(fromUser);
|
||||
|
||||
if (!StringUtil.isNullOrEmpty(message.getToUser())) {
|
||||
notifyReceivers.add(message.getToUser());
|
||||
} else if(message.getToList()!=null && !message.getToList().isEmpty()) {
|
||||
@@ -569,9 +635,6 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果是群助手的消息,返回pull type group,否则返回normal
|
||||
//群助手还没有实现
|
||||
pullType = ProtoConstants.PullType.Pull_Normal;
|
||||
} else if (type == ProtoConstants.ConversationType.ConversationType_ChatRoom) {
|
||||
boolean isDirect = !StringUtil.isNullOrEmpty(message.getToUser());
|
||||
@@ -749,7 +812,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
if (bundle.getMessage().getContent().getExpireDuration() > 0) {
|
||||
if (System.currentTimeMillis() > bundle.getMessage().getServerTimestamp() + bundle.getMessage().getContent().getExpireDuration()*1000) {
|
||||
if (System.currentTimeMillis() > bundle.getMessage().getServerTimestamp() + bundle.getMessage().getContent().getExpireDuration()* 1000L) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -777,6 +840,10 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
mReadLock.unlock();
|
||||
}
|
||||
|
||||
if(current == 0) {
|
||||
current = 2;
|
||||
head = 2;
|
||||
}
|
||||
builder.setCurrent(current);
|
||||
builder.setHead(head);
|
||||
return builder.build();
|
||||
@@ -930,7 +997,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
messageSeq = maxPullSeq + 1;
|
||||
}
|
||||
|
||||
if (messageSeq == 0) {
|
||||
if (messageSeq < messageId) {
|
||||
messageSeq = messageId;
|
||||
}
|
||||
|
||||
@@ -942,7 +1009,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1266,6 +1333,9 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
int maxCount = Integer.MAX_VALUE;
|
||||
|
||||
if (!isAdmin) {
|
||||
if (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
boolean isMember = false;
|
||||
boolean isManager = false;
|
||||
WFCMessage.GroupMember gm = getGroupMember(groupId, operator);
|
||||
@@ -1406,18 +1476,22 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
|
||||
void removeFavGroup(String groupId, List<String> memberIds) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
|
||||
databaseStore.removeFavGroup(groupId, memberIds);
|
||||
|
||||
for (String member : memberIds) {
|
||||
userSettingMap.remove(member);
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
for (String member : memberIds) {
|
||||
userSettingMap.remove(member);
|
||||
}
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorCode quitGroup(String operator, String groupId) {
|
||||
public ErrorCode quitGroup(String operator, String groupId, boolean admin) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP);
|
||||
|
||||
@@ -1437,6 +1511,10 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return ErrorCode.ERROR_CODE_NOT_EXIST;
|
||||
}
|
||||
|
||||
if(!admin && groupInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
if (groupInfo.getType() != ProtoConstants.GroupType.GroupType_Free && groupInfo.getOwner() != null && groupInfo.getOwner().equals(operator)) {
|
||||
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
|
||||
Collection<WFCMessage.GroupMember> members = groupMembers.get(groupId);
|
||||
@@ -1479,7 +1557,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
int[] removedCount = new int[1];
|
||||
for (String groupId : groupIds) {
|
||||
removedCount[0] = 0;
|
||||
ErrorCode errorCode = quitGroup(userId, groupId);
|
||||
ErrorCode errorCode = quitGroup(userId, groupId, true);
|
||||
LOG.info("clear user {} group {} result {}", userId, groupId, errorCode);
|
||||
}
|
||||
}
|
||||
@@ -1487,13 +1565,17 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
|
||||
private void removeGroupUserSettings(String groupId, List<String> users) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
|
||||
databaseStore.removeGroupUserSettings(groupId, users);
|
||||
for (String userId:users) {
|
||||
userSettingMap.remove(userId);
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
for (String userId:users) {
|
||||
userSettingMap.remove(userId);
|
||||
}
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1511,6 +1593,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
if (!isAdmin && (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Free ||
|
||||
groupInfo.getType() == ProtoConstants.GroupType.GroupType_Organization ||
|
||||
(groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal)
|
||||
&& (groupInfo.getOwner() == null || !groupInfo.getOwner().equals(operator)))) {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
@@ -1554,13 +1637,21 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
if (!isAdmin) {
|
||||
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted) {
|
||||
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Organization && modifyType != Modify_Group_Extra && modifyType != Modify_Group_Mute && modifyType != Modify_Group_PrivateChat) {
|
||||
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) {
|
||||
boolean isAllow = false;
|
||||
if ((oldInfo.getOwner() != null && oldInfo.getOwner().equals(operator))) {
|
||||
isAllow = true;
|
||||
} else {
|
||||
WFCMessage.GroupMember gm = getGroupMember(groupId, operator);
|
||||
if (gm != null && gm.getType() == GroupMemberType_Manager) {
|
||||
if (gm.getType() == GroupMemberType_Manager) {
|
||||
isAllow = true;
|
||||
}
|
||||
}
|
||||
@@ -1571,9 +1662,8 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
|
||||
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Normal) {
|
||||
if (!operator.equals(oldInfo.getOwner())) {
|
||||
WFCMessage.GroupMember gm = getGroupMember(groupId, operator);
|
||||
boolean isManager = false;
|
||||
if (gm != null && gm.getType() == GroupMemberType_Manager) {
|
||||
if (gm.getType() == GroupMemberType_Manager) {
|
||||
isManager = true;
|
||||
}
|
||||
if (!isManager && modifyType != Modify_Group_Name && modifyType != Modify_Group_Portrait && modifyType != Modify_Group_Extra) {
|
||||
@@ -1667,12 +1757,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);
|
||||
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);
|
||||
return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
|
||||
}
|
||||
@@ -1796,7 +1886,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
@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();
|
||||
IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP);
|
||||
ArrayList<WFCMessage.GroupInfo> out = new ArrayList<>();
|
||||
@@ -1810,6 +1900,14 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1831,6 +1929,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return databaseStore.getUserGroupIds(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCommonGroupIds(String userId1, String userId2) {
|
||||
return databaseStore.getCommonGroupIds(userId1, userId2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorCode getGroupMembers(String fromUser, String groupId, long maxDt, List<WFCMessage.GroupMember> members) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
@@ -1915,6 +2018,10 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
if (!isAdmin && groupInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) {
|
||||
return ErrorCode.ERROR_CODE_NOT_RIGHT;
|
||||
}
|
||||
|
||||
//check the new owner is in member list? is that necessary?
|
||||
long updateDt = System.currentTimeMillis();
|
||||
groupInfo = groupInfo.toBuilder().setOwner(newOwner).setUpdateDt(updateDt).setMemberUpdateDt(updateDt).build();
|
||||
@@ -2072,7 +2179,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin) {
|
||||
public ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin, ByteBuf ackPayload) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
IMap<Long, MessageBundle> mIMap = hzInstance.getMap(MESSAGES_MAP);
|
||||
|
||||
@@ -2084,9 +2191,10 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
if (isAdmin) {
|
||||
canRecall = true;
|
||||
}
|
||||
if (!isAdmin && message.getFromUser().equals(operatorId)) {
|
||||
boolean isExpired = false;
|
||||
if (!canRecall && message.getFromUser().equals(operatorId)) {
|
||||
if (now - message.getServerTimestamp() > mRecallTimeLimit * 1000) {
|
||||
return ErrorCode.ERROR_CODE_RECALL_TIME_EXPIRED;
|
||||
isExpired = true;
|
||||
} else {
|
||||
canRecall = true;
|
||||
}
|
||||
@@ -2103,17 +2211,26 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
canRecall = true;
|
||||
}
|
||||
|
||||
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
|
||||
Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget());
|
||||
if (members == null || members.size() == 0) {
|
||||
members = loadGroupMemberFromDB(hzInstance, message.getConversation().getTarget());
|
||||
}
|
||||
for (WFCMessage.GroupMember member : members) {
|
||||
if (member.getMemberId().equals(operatorId)) {
|
||||
if (member.getType() == GroupMemberType_Manager || member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Owner) {
|
||||
canRecall = true;
|
||||
if(!canRecall && !message.getFromUser().equals(operatorId)) {
|
||||
boolean isOperatorManager = false;
|
||||
int senderType = GroupMemberType_Normal;
|
||||
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
|
||||
Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget());
|
||||
if (members == null || members.size() == 0) {
|
||||
members = loadGroupMemberFromDB(hzInstance, message.getConversation().getTarget());
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2125,13 +2242,30 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
json.put("s", message.getFromUser());
|
||||
json.put("ts", message.getServerTimestamp());
|
||||
@@ -2171,6 +2305,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
databaseStore.deleteMessage(messageUid);
|
||||
|
||||
mIMap.put(messageUid, messageBundle, 7, TimeUnit.DAYS);
|
||||
ackPayload.writeBytes(recalledContent.getBytes(StandardCharsets.UTF_8));
|
||||
return ErrorCode.ERROR_CODE_SUCCESS;
|
||||
} else {
|
||||
return ErrorCode.ERROR_CODE_NOT_EXIST;
|
||||
@@ -2385,6 +2520,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
|
||||
public void updateUserOnlineSetting(MemorySessionStore.Session session, boolean online) {
|
||||
if(!mMultiPlatformNotification) {
|
||||
@@ -2416,14 +2573,8 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
WFCMessage.UserSettingEntry pcentry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "PC");
|
||||
if (pcValue != null) {
|
||||
if (pcentry == null || StringUtil.isNullOrEmpty(pcentry.getValue())) {
|
||||
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);
|
||||
}
|
||||
if (!isOnlineValueEqual(pcentry, pcValue)) {
|
||||
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue(pcValue==null?"":pcValue).build(), session.clientID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2616,6 +2767,12 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
String userId = databaseStore.getUserIdByMobile(mobile);
|
||||
return getUserInfo(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WFCMessage.User> getUserInfoList(int count, int offset) {
|
||||
return databaseStore.getAllUsers(count, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) {
|
||||
if (mDisableSearch) {
|
||||
@@ -2779,6 +2936,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
|
||||
|
||||
if (mDisableStrangerChat) {
|
||||
//在禁止私聊时,是否是允许私聊的用户id
|
||||
if(mAllowStrangerChatSet.contains(targetUser)) {
|
||||
return ErrorCode.ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
//在禁止私聊时,允许机器人,物联网设备及管理员进行私聊。
|
||||
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
|
||||
WFCMessage.User target = mUserMap.get(targetUser);
|
||||
@@ -2948,27 +3110,16 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
}
|
||||
|
||||
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FriendData friendData1 = getFriendData(userId, request.getTargetUid());
|
||||
if (friendData1 != null && friendData1.getState() == 0) {
|
||||
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
|
||||
.newBuilder()
|
||||
.setFromUid(userId)
|
||||
@@ -3080,7 +3231,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
friendsMap.remove(userId);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -3346,7 +3497,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
}
|
||||
|
||||
private String ensureSecretLength(String secret) {
|
||||
while ( secret.length() < 16) {
|
||||
while ( secret.length() < AES.keyLen) {
|
||||
secret += "w";
|
||||
secret += secret;
|
||||
}
|
||||
@@ -3548,9 +3699,15 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
IMap<String, WFCMessage.GroupInfo> mGroups = hzInstance.getMap(GROUPS_MAP);
|
||||
IMap<String, WFCMessage.ChannelInfo> mChannels = hzInstance.getMap(CHANNELS);
|
||||
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
Collection<WFCMessage.UserSettingEntry> entries;
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
}
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
ErrorCode ec = ErrorCode.ERROR_CODE_NOT_MODIFIED;
|
||||
@@ -3629,17 +3786,22 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
}
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
}
|
||||
|
||||
if (entries != null) {
|
||||
for (WFCMessage.UserSettingEntry entry : entries) {
|
||||
if (entry.getScope() == scope && (key== null || key.equals(entry.getKey()))) {
|
||||
return entry;
|
||||
if (entries != null) {
|
||||
for (WFCMessage.UserSettingEntry entry : entries) {
|
||||
if (entry.getScope() == scope && (key== null || key.equals(entry.getKey()))) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -3650,19 +3812,25 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
}
|
||||
List<WFCMessage.UserSettingEntry> result;
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
}
|
||||
|
||||
List<WFCMessage.UserSettingEntry> result = new ArrayList<>();
|
||||
if (entries != null) {
|
||||
for (WFCMessage.UserSettingEntry entry : entries
|
||||
) {
|
||||
if (entry.getScope() == scope) {
|
||||
result.add(entry);
|
||||
result = new ArrayList<>();
|
||||
if (entries != null) {
|
||||
for (WFCMessage.UserSettingEntry entry : entries
|
||||
) {
|
||||
if (entry.getScope() == scope) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -3673,28 +3841,34 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
if (entries == null) {
|
||||
entries = new ArrayList<>();
|
||||
long updateDt = 0;
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
Collection<WFCMessage.UserSettingEntry> entries = userSettingMap.get(userId);
|
||||
if (entries == null || entries.size() == 0) {
|
||||
entries = loadPersistedUserSettings(userId, userSettingMap);
|
||||
if (entries == null) {
|
||||
entries = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long updateDt = System.currentTimeMillis();
|
||||
WFCMessage.UserSettingEntry settingEntry = WFCMessage.UserSettingEntry.newBuilder().setScope(request.getScope()).setKey(request.getKey()).setValue(request.getValue()).setUpdateDt(updateDt).build();
|
||||
databaseStore.persistUserSetting(userId, settingEntry);
|
||||
updateDt = System.currentTimeMillis();
|
||||
WFCMessage.UserSettingEntry settingEntry = WFCMessage.UserSettingEntry.newBuilder().setScope(request.getScope()).setKey(request.getKey()).setValue(request.getValue()).setUpdateDt(updateDt).build();
|
||||
databaseStore.persistUserSetting(userId, settingEntry);
|
||||
|
||||
for (WFCMessage.UserSettingEntry entry : entries
|
||||
) {
|
||||
if (entry.getScope() == request.getScope() && entry.getKey().equals(request.getKey())) {
|
||||
userSettingMap.remove(userId, entry);
|
||||
userSettingMap.put(userId, settingEntry);
|
||||
break;
|
||||
for (WFCMessage.UserSettingEntry entry : entries
|
||||
) {
|
||||
if (entry.getScope() == request.getScope() && entry.getKey().equals(request.getKey())) {
|
||||
userSettingMap.remove(userId, entry);
|
||||
userSettingMap.put(userId, settingEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userSettingMap.put(userId, settingEntry);
|
||||
userSettingMap.put(userId, settingEntry);
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
|
||||
if(request.getScope() == UserSettingScope.kUserSettingConversationSilent) {
|
||||
int firstSplit = request.getKey().indexOf("-");
|
||||
@@ -3719,8 +3893,14 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
public void clearUserSettings(String userId) {
|
||||
databaseStore.clearUserSetting(userId);
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
userSettingMap.remove(userId);
|
||||
|
||||
try {
|
||||
mUserSettingLock.lock();
|
||||
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
|
||||
userSettingMap.remove(userId);
|
||||
} finally {
|
||||
mUserSettingLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3962,6 +4142,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return databaseStore.searchChannelFromDB(keyword, buzzy, page);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getListenedChannels(String userId) {
|
||||
return databaseStore.getUserChannels(userId);
|
||||
}
|
||||
@Override
|
||||
public ErrorCode listenChannel(String operator, String channelId, boolean listen) {
|
||||
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
|
||||
@@ -4111,6 +4296,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return mGroupVisibleQuitKickoffNotification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupForbiddenClientOperation() {
|
||||
return mGroupForbiddenClientOperation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForwardMessageWithClientInfo() {
|
||||
return mForwardMessageWithClientInfo;
|
||||
@@ -4126,6 +4316,11 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return mChannelCallbackWithClientInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRobotAutoAcceptFriendRequest() {
|
||||
return mFriendRobotAutoAccept;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getClientForbiddenSendTypes() {
|
||||
return mForbiddenClientSendTypes;
|
||||
@@ -4251,6 +4446,34 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
return UUIDGenerator.getUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkSignature(String signature) {
|
||||
if(mClientSignatureSet.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(StringUtil.isNullOrEmptyAfterTrim(signature)) {
|
||||
if(mRejectEmptySignature) {
|
||||
LOG.info("Failed check signature, no signature");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if(mClientSignatureSet.contains(signature)) {
|
||||
return true;
|
||||
} else {
|
||||
LOG.info("Failed check signature, signature no matched");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existSignatures() {
|
||||
return !mClientSignatureSet.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeRetained(Topic topic, StoredMessage storedMessage) {
|
||||
LOG.debug("Store retained message for topic={}, CId={}", topic, storedMessage.getClientID());
|
||||
|
||||
@@ -232,18 +232,6 @@ public class Server {
|
||||
handlers = Collections.emptyList();
|
||||
}
|
||||
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));
|
||||
|
||||
@@ -393,9 +381,13 @@ public class Server {
|
||||
|
||||
longPort = config.getProperty(BrokerConstants.PORT_PROPERTY_NAME);
|
||||
shortPort = config.getProperty(BrokerConstants.HTTP_SERVER_PORT);
|
||||
boolean aes256 = Boolean.parseBoolean(config.getProperty(ENCRYPT_AES256, "false"));
|
||||
|
||||
MessageShardingUtil.setNodeId(1);
|
||||
Tokenor.setKey(config.getProperty(BrokerConstants.TOKEN_SECRET_KEY));
|
||||
|
||||
AES.useAes256(aes256);
|
||||
|
||||
String expirTimeStr = config.getProperty(TOKEN_EXPIRE_TIME);
|
||||
if (!StringUtil.isNullOrEmpty(expirTimeStr)) {
|
||||
try {
|
||||
|
||||
@@ -110,15 +110,16 @@ public interface IMessagesStore {
|
||||
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin);
|
||||
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra);
|
||||
ErrorCode kickoffGroupMembers(String operator, boolean isAdmin, String groupId, List<String> memberList);
|
||||
ErrorCode quitGroup(String operator, String groupId);
|
||||
ErrorCode quitGroup(String operator, String groupId, boolean admin);
|
||||
void clearUserGroups(String userId);
|
||||
ErrorCode dismissGroup(String operator, String groupId, boolean isAdmin);
|
||||
ErrorCode modifyGroupInfo(String operator, String groupId, int modifyType, String value, boolean isAdmin);
|
||||
ErrorCode modifyGroupMemberAlias(String operator, String groupId, String alias, 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);
|
||||
Set<String> getUserGroupIds(String userId);
|
||||
Set<String> getCommonGroupIds(String userId1, String userId2);
|
||||
ErrorCode getGroupMembers(String fromUser, String groupId, long maxDt, List<WFCMessage.GroupMember> members);
|
||||
WFCMessage.GroupMember getGroupMember(String groupId, String memberId);
|
||||
ErrorCode transferGroup(String operator, String groupId, String newOwner, boolean isAdmin);
|
||||
@@ -127,7 +128,7 @@ public interface IMessagesStore {
|
||||
ErrorCode canSendMessageInGroup(String member, String groupId);
|
||||
Set<String> getGroupManagers(String groupId, boolean includeOwner);
|
||||
|
||||
ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin);
|
||||
ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin, ByteBuf ackPayload);
|
||||
ErrorCode recallCastMessage(long messageUid, String operatorId);
|
||||
|
||||
void clearUserMessages(String userId);
|
||||
@@ -157,6 +158,8 @@ public interface IMessagesStore {
|
||||
WFCMessage.User getUserInfoByMobile(String mobile);
|
||||
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);
|
||||
SystemSettingPojo getSystemSetting(int id);
|
||||
void createChatroom(String chatroomId, WFCMessage.ChatroomInfo chatroomInfo);
|
||||
@@ -215,6 +218,7 @@ public interface IMessagesStore {
|
||||
ErrorCode transferChannel(String operator, String channelId, String newOwner);
|
||||
ErrorCode destroyChannel(String operator, String channelId, boolean isAdmin);
|
||||
List<WFCMessage.ChannelInfo> searchChannel(String keyword, boolean buzzy, int page);
|
||||
List<String> getListenedChannels(String userId);
|
||||
ErrorCode listenChannel(String operator, String channelId, boolean listen);
|
||||
WFCMessage.ChannelInfo getChannelInfo(String channelId);
|
||||
boolean canSendMessageInChannel(String user, String channelId);
|
||||
@@ -232,10 +236,14 @@ public interface IMessagesStore {
|
||||
boolean isAllowRobotCustomGroupNotification();
|
||||
int getVisibleQuitKickoffNotification();
|
||||
|
||||
int getGroupForbiddenClientOperation();
|
||||
|
||||
boolean isForwardMessageWithClientInfo();
|
||||
boolean isRobotCallbackWithClientInfo();
|
||||
boolean isChannelCallbackWithClientInfo();
|
||||
|
||||
boolean isRobotAutoAcceptFriendRequest();
|
||||
|
||||
List<Integer> getClientForbiddenSendTypes();
|
||||
List<Integer> getBlackListExceptionTypes();
|
||||
List<Integer> getGroupMuteExceptionTypes();
|
||||
@@ -248,6 +256,9 @@ public interface IMessagesStore {
|
||||
|
||||
//使用了数据库,会比较慢,仅能用户用户/群组等id的生成
|
||||
String getShortUUID();
|
||||
|
||||
boolean checkSignature(String signature);
|
||||
boolean existSignatures();
|
||||
/**
|
||||
* Used to initialize all persistent store structures
|
||||
*/
|
||||
|
||||
@@ -35,14 +35,11 @@ import io.moquette.spi.ISessionsStore;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.mqtt.*;
|
||||
import win.liyufan.im.GsonUtil;
|
||||
import win.liyufan.im.HttpUtils;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.*;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import win.liyufan.im.Utility;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -168,6 +165,9 @@ public class MessagesPublisher {
|
||||
}
|
||||
|
||||
WFCMessage.Message message = null;
|
||||
String senderName = null;
|
||||
String senderPortrait = null;
|
||||
boolean sendNameLoaded = false;
|
||||
for (String user : receivers) {
|
||||
if (!user.equals(sender)) {
|
||||
WFCMessage.User userInfo = m_messagesStore.getUserInfo(user);
|
||||
@@ -207,10 +207,10 @@ public class MessagesPublisher {
|
||||
}
|
||||
|
||||
Collection<Session> sessions = m_sessionsStore.sessionForUser(user);
|
||||
String senderName = null;
|
||||
String targetName = null;
|
||||
boolean nameLoaded = false;
|
||||
|
||||
String targetName = null;
|
||||
String targetPortrait = null;
|
||||
boolean targetNameLoaded = false;
|
||||
|
||||
Collection<String> targetClients = null;
|
||||
if (pullType == ProtoConstants.PullType.Pull_ChatRoom) {
|
||||
@@ -386,10 +386,22 @@ public class MessagesPublisher {
|
||||
|
||||
boolean isHiddenDetail = m_messagesStore.getUserPushHiddenDetail(user);
|
||||
|
||||
if(!nameLoaded) {
|
||||
senderName = getUserDisplayName(sender, conversationType == ProtoConstants.ConversationType.ConversationType_Group ? target : null);
|
||||
targetName = getTargetName(target, conversationType);
|
||||
nameLoaded = true;
|
||||
if(!sendNameLoaded) {
|
||||
List<String> list = new ArrayList<>();
|
||||
senderName = getUserDisplayName(sender, conversationType == ProtoConstants.ConversationType.ConversationType_Group ? target : null, list);
|
||||
if(!list.isEmpty()) {
|
||||
senderPortrait = list.get(0);
|
||||
}
|
||||
sendNameLoaded = true;
|
||||
}
|
||||
|
||||
if(!targetNameLoaded) {
|
||||
List<String> list = new ArrayList<>();
|
||||
targetName = getTargetName(target, conversationType, user, list);
|
||||
if(!list.isEmpty()) {
|
||||
targetPortrait = list.get(0);
|
||||
}
|
||||
targetNameLoaded = true;
|
||||
}
|
||||
|
||||
String name = senderName;
|
||||
@@ -399,7 +411,7 @@ public class MessagesPublisher {
|
||||
name = fd.getAlias();
|
||||
}
|
||||
}
|
||||
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, messageContentType, serverTime, name, targetName, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
|
||||
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, messageContentType, serverTime, name, senderPortrait, targetName, targetPortrait, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -461,10 +473,13 @@ public class MessagesPublisher {
|
||||
}
|
||||
}
|
||||
|
||||
String getUserDisplayName(String userId, String groupId) {
|
||||
String getUserDisplayName(String userId, String groupId, List<String> portraitList) {
|
||||
WFCMessage.User user = m_messagesStore.getUserInfo(userId);
|
||||
String userName = null;
|
||||
if(user != null) {
|
||||
if(portraitList != null && !StringUtil.isNullOrEmpty(user.getPortrait())) {
|
||||
portraitList.add(user.getPortrait());
|
||||
}
|
||||
userName = user.getDisplayName();
|
||||
}
|
||||
if (!StringUtil.isNullOrEmpty(groupId)) {
|
||||
@@ -476,17 +491,28 @@ public class MessagesPublisher {
|
||||
return userName;
|
||||
}
|
||||
|
||||
String getTargetName(String targetId, int cnvType) {
|
||||
String getTargetName(String targetId, int cnvType, String fromUser, List<String> portraitList) {
|
||||
if (cnvType == ProtoConstants.ConversationType.ConversationType_Private) {
|
||||
return getUserDisplayName(targetId, null);
|
||||
return getUserDisplayName(targetId, null, portraitList);
|
||||
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Group) {
|
||||
WFCMessage.GroupInfo group = m_messagesStore.getGroupInfo(targetId);
|
||||
if(group != null) {
|
||||
if(!StringUtil.isNullOrEmpty(group.getPortrait())) {
|
||||
portraitList.add(group.getPortrait());
|
||||
}
|
||||
|
||||
WFCMessage.UserSettingEntry entry = m_messagesStore.getUserSetting(fromUser, UserSettingScope.kUserSettingGroupRemark, targetId);
|
||||
if(entry != null && !StringUtil.isNullOrEmpty(entry.getValue())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
return group.getName();
|
||||
}
|
||||
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Channel) {
|
||||
WFCMessage.ChannelInfo channelInfo = m_messagesStore.getChannelInfo(targetId);
|
||||
if (channelInfo != null) {
|
||||
if(!StringUtil.isNullOrEmpty(channelInfo.getPortrait())) {
|
||||
portraitList.add(channelInfo.getPortrait());
|
||||
}
|
||||
return channelInfo.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ class PersistentQueueMessageSender {
|
||||
this.connectionDescriptorStore = connectionDescriptorStore;
|
||||
}
|
||||
|
||||
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, int messageContentType, long serverTime, String senderName, String targetName, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language) {
|
||||
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language) {
|
||||
LOG.info("Send push to {}, message from {}", deviceId, sender);
|
||||
PushMessage pushMessage = new PushMessage(sender, conversationType, target, line, messageContentType, serverTime, senderName, targetName, unReceivedMsg, mentionType, isHiddenDetail, language);
|
||||
PushMessage pushMessage = new PushMessage(sender, conversationType, target, line, messageContentType, serverTime, senderName, senderPortrait, targetName, targetPortrait, unReceivedMsg, mentionType, isHiddenDetail, language);
|
||||
pushMessage.pushContent = pushContent;
|
||||
pushMessage.pushData = pushData;
|
||||
pushMessage.messageId = messageId;
|
||||
|
||||
@@ -48,6 +48,7 @@ import win.liyufan.im.HttpUtils;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.Utility;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -107,7 +108,7 @@ public class ProtocolProcessor {
|
||||
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
|
||||
try {
|
||||
if (descriptor != null) {
|
||||
processDisconnect(descriptor.getChannel(), true, false);
|
||||
processDisconnect(descriptor.getChannel(), false, false);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
@@ -339,6 +340,24 @@ public class ProtocolProcessor {
|
||||
failedCredentials(channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(session.getPlatform() == ProtoConstants.Platform.Platform_Android || session.getPlatform() == ProtoConstants.Platform.Platform_APad) {
|
||||
byte[] signature = msg.payload().signatureInBytes();
|
||||
String basedSign = null;
|
||||
if (signature != null && signature.length > 0) {
|
||||
signature = AES.AESDecrypt(signature, session.getSecret(), true);
|
||||
}
|
||||
if (signature != null && signature.length > 0) {
|
||||
basedSign = Base64.getEncoder().encodeToString(signature);
|
||||
}
|
||||
|
||||
if (!m_messagesStore.checkSignature(basedSign)) {
|
||||
LOG.error("Bad signature of session <{}, {}>", session.getUsername(), session.getClientID());
|
||||
failedBadSignature(channel);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
session.setMqttVersion(mqttVersion);
|
||||
} else {
|
||||
LOG.error("Client didn't supply any password and MQTT anonymous mode is disabled CId={}", clientId);
|
||||
@@ -446,6 +465,11 @@ public class ProtocolProcessor {
|
||||
LOG.info("Client {} failed to connect with bad username or password.", session);
|
||||
}
|
||||
|
||||
private void failedBadSignature(Channel session) {
|
||||
session.writeAndFlush(connAck(CONNECTION_REFUSED_SIGNATURE_FAILURE));
|
||||
LOG.info("Client {} failed to connect with bad signature.", session);
|
||||
}
|
||||
|
||||
private void setIdleTime(ChannelPipeline pipeline, int idleTime) {
|
||||
if (pipeline.names().contains("idleStateHandler")) {
|
||||
pipeline.remove("idleStateHandler");
|
||||
@@ -584,8 +608,9 @@ public class ProtocolProcessor {
|
||||
channel.closeFuture();
|
||||
|
||||
//disconnect the session
|
||||
|
||||
m_sessionsStore.sessionForClient(clientID).disconnect(session.getUsername(), isDup, isRetain);
|
||||
if(session != null) {
|
||||
m_sessionsStore.sessionForClient(clientID).disconnect(session.getUsername(), isDup, isRetain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,12 +651,22 @@ public class ProtocolProcessor {
|
||||
if(connectionDescriptors.removeConnection(oldConnDescr)) {
|
||||
m_interceptor.notifyClientConnectionLost(clientID, username);
|
||||
}
|
||||
try {
|
||||
channel.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel);
|
||||
if(connectionDescriptors.removeConnection(oldConnDescr)) {
|
||||
m_interceptor.notifyClientConnectionLost(clientID, username);
|
||||
}
|
||||
try {
|
||||
channel.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -243,15 +243,17 @@ public class Qos1PublishHandler extends QosPublishHandler {
|
||||
String imtopic = topic.getTopic();
|
||||
ByteBuf payload = msg.payload();
|
||||
byte[] payloadContent = readBytesAndRewind(payload);
|
||||
if(payloadContent.length == 0) {
|
||||
ByteBuf ackPayload = Unpooled.buffer();
|
||||
ackPayload.ensureWritable(1).writeByte(ERROR_CODE_INVALID_DATA.getCode());
|
||||
sendPubAck(clientID, messageID, ackPayload, ERROR_CODE_INVALID_DATA);
|
||||
return;
|
||||
if(payloadContent.length > 0) {
|
||||
MemorySessionStore.Session session = m_sessionStore.getSession(clientID);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
MemorySessionStore.Session session = m_sessionStore.getSession(clientID);
|
||||
payloadContent = AES.AESDecrypt(payloadContent, session.getSecret(), true);
|
||||
|
||||
imHandler(clientID, username, imtopic, payloadContent, (errorCode, ackPayload) -> sendPubAck(clientID, messageID, ackPayload, errorCode), ProtoConstants.RequestSourceType.Request_From_User);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public final class MqttConnectPayload {
|
||||
private final byte[] willMessage;
|
||||
private final String userName;
|
||||
private final byte[] password;
|
||||
private final byte[] signature;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link MqttConnectPayload#MqttConnectPayload(String,
|
||||
@@ -50,7 +51,7 @@ public final class MqttConnectPayload {
|
||||
willTopic,
|
||||
willMessage.getBytes(CharsetUtil.UTF_8),
|
||||
userName,
|
||||
password.getBytes(CharsetUtil.UTF_8));
|
||||
password.getBytes(CharsetUtil.UTF_8), null);
|
||||
}
|
||||
|
||||
public MqttConnectPayload(
|
||||
@@ -64,7 +65,7 @@ public final class MqttConnectPayload {
|
||||
willTopic,
|
||||
willMessage,
|
||||
userName,
|
||||
password);
|
||||
password, null);
|
||||
}
|
||||
|
||||
public MqttConnectPayload(
|
||||
@@ -73,13 +74,15 @@ public final class MqttConnectPayload {
|
||||
String willTopic,
|
||||
byte[] willMessage,
|
||||
String userName,
|
||||
byte[] password) {
|
||||
byte[] password,
|
||||
byte[] signature) {
|
||||
this.clientIdentifier = clientIdentifier;
|
||||
this.willProperties = MqttProperties.withEmptyDefaults(willProperties);
|
||||
this.willTopic = willTopic;
|
||||
this.willMessage = willMessage;
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String clientIdentifier() {
|
||||
@@ -122,6 +125,10 @@ public final class MqttConnectPayload {
|
||||
return password;
|
||||
}
|
||||
|
||||
public byte[] signatureInBytes() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(StringUtil.simpleClassName(this))
|
||||
|
||||
@@ -29,6 +29,7 @@ public enum MqttConnectReturnCode {
|
||||
CONNECTION_REFUSED_NOT_AUTHORIZED((byte) 0x05),
|
||||
CONNECTION_REFUSED_UNEXPECT_NODE((byte) 0X06),
|
||||
CONNECTION_REFUSED_SESSION_NOT_EXIST((byte) 0x07),
|
||||
CONNECTION_REFUSED_SIGNATURE_FAILURE((byte) 0x08),
|
||||
//MQTT 5 codes
|
||||
CONNECTION_REFUSED_UNSPECIFIED_ERROR((byte) 0x80),
|
||||
CONNECTION_REFUSED_MALFORMED_PACKET((byte) 0x81),
|
||||
|
||||
@@ -146,7 +146,7 @@ public final class MqttDecoder extends ReplayingDecoder<MqttDecoder.DecoderState
|
||||
* bytes for the remaining length.
|
||||
*
|
||||
* @see
|
||||
* https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180841
|
||||
* <a href="https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180841">...</a>
|
||||
*
|
||||
* @param buffer the buffer to decode from
|
||||
* @return the fixed header
|
||||
@@ -534,7 +534,7 @@ public final class MqttDecoder extends ReplayingDecoder<MqttDecoder.DecoderState
|
||||
|
||||
final MqttProperties willProperties;
|
||||
if (mqttConnectVariableHeader.isWillFlag()) {
|
||||
if (mqttVersion == MqttVersion.MQTT_5) {
|
||||
if (mqttVersion.protocolLevel() <= MqttVersion.MQTT_5.protocolLevel()) {
|
||||
final Result<MqttProperties> propertiesResult = decodeProperties(buffer);
|
||||
willProperties = propertiesResult.value;
|
||||
numberOfBytesConsumed += propertiesResult.numberOfBytesConsumed;
|
||||
@@ -550,6 +550,7 @@ public final class MqttDecoder extends ReplayingDecoder<MqttDecoder.DecoderState
|
||||
}
|
||||
Result<String> decodedUserName = null;
|
||||
byte[] decodedPassword = null;
|
||||
byte[] decodedSignature = null;
|
||||
if (mqttConnectVariableHeader.hasUserName()) {
|
||||
decodedUserName = decodeString(buffer);
|
||||
numberOfBytesConsumed += decodedUserName.numberOfBytesConsumed;
|
||||
@@ -558,6 +559,10 @@ public final class MqttDecoder extends ReplayingDecoder<MqttDecoder.DecoderState
|
||||
decodedPassword = decodeByteArray(buffer);
|
||||
numberOfBytesConsumed += decodedPassword.length + 2;
|
||||
}
|
||||
if (mqttConnectVariableHeader.isWillRetain()) {
|
||||
decodedSignature = decodeByteArray(buffer);
|
||||
numberOfBytesConsumed += decodedSignature.length + 2;
|
||||
}
|
||||
|
||||
final MqttConnectPayload mqttConnectPayload =
|
||||
new MqttConnectPayload(
|
||||
@@ -566,7 +571,9 @@ public final class MqttDecoder extends ReplayingDecoder<MqttDecoder.DecoderState
|
||||
decodedWillTopic != null ? decodedWillTopic.value : null,
|
||||
decodedWillMessage,
|
||||
decodedUserName != null ? decodedUserName.value : null,
|
||||
decodedPassword);
|
||||
decodedPassword,
|
||||
decodedSignature
|
||||
);
|
||||
return new Result<MqttConnectPayload>(mqttConnectPayload, numberOfBytesConsumed);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ public final class MqttMessageBuilders {
|
||||
keepAliveSecs,
|
||||
properties);
|
||||
MqttConnectPayload mqttConnectPayload =
|
||||
new MqttConnectPayload(clientId, willProperties, willTopic, willMessage, username, password);
|
||||
new MqttConnectPayload(clientId, willProperties, willTopic, willMessage, username, password, null);
|
||||
return new MqttConnectMessage(mqttFixedHeader, mqttConnectVariableHeader, mqttConnectPayload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ public class HttpUtils {
|
||||
POST_TYPE_Channel_Message_Callback,
|
||||
POST_TYPE_Forward_Message_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) {
|
||||
@@ -88,7 +89,7 @@ public class HttpUtils {
|
||||
System.out.println(logText);
|
||||
e.printStackTrace();
|
||||
LOG.error(logText);
|
||||
LOG.error("POST to {} with data {} failure", url, jsonStr);
|
||||
LOG.error("POST to {} failed", url);
|
||||
if(httpCallback != null) {
|
||||
httpCallback.onFailure(-1, e.getMessage());
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ public interface IMTopic {
|
||||
String GetGroupMemberTopic = "GPGM";
|
||||
String TransferGroupTopic = "GTG";
|
||||
String SetGroupManagerTopic = "GSM";
|
||||
String GetMyGroupsTopic = "GMGS";
|
||||
String GetCommonGroupsTopic = "GCGS";
|
||||
|
||||
String GetUserInfoTopic = "UPUI";
|
||||
String ModifyMyInfoTopic = "MMI";
|
||||
@@ -75,6 +77,7 @@ public interface IMTopic {
|
||||
String ChannelSearchTopic = "CHS";
|
||||
String ChannelListenTopic = "CHL";
|
||||
String ChannelPullTopic = "CHP";
|
||||
String ListenedChannelListTopic = "CHLL";
|
||||
|
||||
String GetTokenTopic = "GETTOKEN";
|
||||
String DestroyUserTopic = "DESTROYUSER";
|
||||
|
||||
@@ -14,5 +14,10 @@ public interface UserSettingScope {
|
||||
int kUserSettingConversationDraft = 19;
|
||||
int kUserSettingDisableSyncDraft = 20;
|
||||
int kUserSettingVoipSilent = 21;
|
||||
|
||||
int kUserSettingPttReserved = 22;
|
||||
int kUserSettingCustomState = 23;
|
||||
int kUserSettingDisableSecretChat = 24;
|
||||
int kUserSettingPttSilent = 25;
|
||||
int kUserSettingGroupRemark = 26;
|
||||
int kUserSettingPrivacySearchable = 27;
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
|
||||
<RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false"
|
||||
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>
|
||||
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
</Filters>
|
||||
<PatternLayout pattern="${pattern}" />
|
||||
<Policies>
|
||||
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
|
||||
<!-- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>-->
|
||||
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
|
||||
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
|
||||
<SizeBasedTriggeringPolicy size="100 MB"/>
|
||||
</Policies>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.97</version>
|
||||
<version>1.1.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ public interface APIPath {
|
||||
String User_Get_Token = "/admin/user/get_token";
|
||||
String User_Update_Block_Status = "/admin/user/update_block_status";
|
||||
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_Blocked_List = "/admin/user/get_blocked_list";
|
||||
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_Modify_Info = "/admin/group/modify";
|
||||
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_Kickoff = "/admin/group/member/del";
|
||||
String Group_Member_Quit = "/admin/group/member/quit";
|
||||
@@ -77,6 +79,7 @@ public interface APIPath {
|
||||
String Get_User_Groups = "/admin/group/of_user";
|
||||
String Group_Set_Member_Alias = "/admin/group/member/set_alias";
|
||||
String Group_Set_Member_Extra = "/admin/group/member/set_extra";
|
||||
String Get_Common_Groups = "/admin/group/common_group";
|
||||
|
||||
String Create_Channel = "/admin/channel/create";
|
||||
String Destroy_Channel = "/admin/channel/destroy";
|
||||
@@ -89,10 +92,14 @@ public interface APIPath {
|
||||
String Health = "/admin/health";
|
||||
|
||||
String Conference_List = "/admin/conference/list";
|
||||
String Conference_Exist = "/admin/conference/exist";
|
||||
String Conference_List_Participant = "/admin/conference/list_participant";
|
||||
String Conference_Create = "/admin/conference/create";
|
||||
String Conference_Destroy = "/admin/conference/destroy";
|
||||
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_Update_Profile = "/channel/update_profile";
|
||||
@@ -100,6 +107,7 @@ public interface APIPath {
|
||||
String Channel_Message_Send = "/channel/message/send";
|
||||
String Channel_Subscribe = "/channel/subscribe";
|
||||
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 Robot_User_Info = "/robot/user_info";
|
||||
@@ -116,6 +124,7 @@ public interface APIPath {
|
||||
String Robot_Group_Dismiss = "/robot/group/del";
|
||||
String Robot_Group_Get_Info = "/robot/group/get_info";
|
||||
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_Modify_Info = "/robot/group/modify";
|
||||
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_ROBOT_NO_TOKEN(27, "robot no token"),
|
||||
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_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_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_CHANNEL_NO_EXIST(236, "channel no exist"),
|
||||
@@ -72,7 +75,7 @@ public enum ErrorCode {
|
||||
ERROR_CODE_SENSITIVE_MATCHED(242, "sensitive matched"),
|
||||
ERROR_CODE_SIGN_EXPIRED(243, "sign expired"),
|
||||
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_FORBIDDEN_SEND_MSG(247, "forbidden send msg globally"),
|
||||
ERROR_CODE_NOT_RIGHT(248, "no right to operate"),
|
||||
|
||||
@@ -3,5 +3,7 @@ package cn.wildfirechat.pojos;
|
||||
public class ConferenceLeaveEvent {
|
||||
public String userId;
|
||||
public String roomId;
|
||||
public boolean rejoin;
|
||||
public boolean kicked;
|
||||
public boolean screenSharing;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ public class InputCreateGroup extends InputGroupBase {
|
||||
if(group_info.max_member_count > 0) {
|
||||
groupInfoBuilder.setMaxMemberCount(group_info.max_member_count);
|
||||
}
|
||||
if(group_info.isSuper_group()) {
|
||||
groupInfoBuilder.setSuperGroup(1);
|
||||
}
|
||||
|
||||
groupBuilder.setGroupInfo(groupInfoBuilder);
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PojoConferenceParticipant {
|
||||
public static class Stream {
|
||||
public String type;
|
||||
public String mid;
|
||||
public String codec;
|
||||
}
|
||||
|
||||
public String userId;
|
||||
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 max_member_count;
|
||||
int history_message;
|
||||
boolean super_group;
|
||||
|
||||
public String getTarget_id() {
|
||||
return target_id;
|
||||
@@ -117,4 +118,12 @@ public class PojoGroupInfo {
|
||||
public void setHistory_message(int 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_Channel = 3;
|
||||
int ConversationType_Things = 4;
|
||||
int ConversationType_SecretChat = 5;
|
||||
}
|
||||
|
||||
//message GroupInfo -> type
|
||||
@@ -19,6 +20,8 @@ public class ProtoConstants {
|
||||
int GroupType_Free = 1;
|
||||
//member can only quit, owner can do all the operations
|
||||
int GroupType_Restricted = 2;
|
||||
//member can not do anything, server api manage the group
|
||||
int GroupType_Organization = 3;
|
||||
}
|
||||
|
||||
//message GroupMember -> type
|
||||
@@ -153,6 +156,8 @@ public class ProtoConstants {
|
||||
int Modify_Group_History_Message = 7;
|
||||
//仅专业版的server api支持
|
||||
int Modify_Group_Max_Member_Count = 8;
|
||||
//仅专业版的server api支持
|
||||
int Modify_Group_Super_Group = 9;
|
||||
}
|
||||
|
||||
//ModifyGroupInfoRequest -> type
|
||||
@@ -215,6 +220,12 @@ public class ProtoConstants {
|
||||
int SearchUserType_Mobile = 3;
|
||||
}
|
||||
|
||||
public interface DisableSearchMask {
|
||||
int DisableSearchDisplayNameMask = 1;
|
||||
int DisableSearchNameMask = 2;
|
||||
int DisableSearchMobileMask = 4;
|
||||
}
|
||||
|
||||
public interface UserStatus {
|
||||
int Normal = 0;
|
||||
int Muted = 1;
|
||||
@@ -290,6 +301,34 @@ public class ProtoConstants {
|
||||
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_ADD_GROUP_MEMBER = 105;
|
||||
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>
|
||||
*/
|
||||
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}
|
||||
@@ -1768,6 +1778,11 @@ public final class WFCMessage {
|
||||
historyMessage_ = input.readInt32();
|
||||
break;
|
||||
}
|
||||
case 128: {
|
||||
bitField0_ |= 0x00008000;
|
||||
superGroup_ = input.readInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
@@ -2183,6 +2198,22 @@ public final class WFCMessage {
|
||||
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() {
|
||||
targetId_ = "";
|
||||
name_ = "";
|
||||
@@ -2199,6 +2230,7 @@ public final class WFCMessage {
|
||||
searchable_ = 0;
|
||||
maxMemberCount_ = 0;
|
||||
historyMessage_ = 0;
|
||||
superGroup_ = 0;
|
||||
}
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
@@ -2265,6 +2297,9 @@ public final class WFCMessage {
|
||||
if (((bitField0_ & 0x00004000) == 0x00004000)) {
|
||||
output.writeInt32(15, historyMessage_);
|
||||
}
|
||||
if (((bitField0_ & 0x00008000) == 0x00008000)) {
|
||||
output.writeInt32(16, superGroup_);
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -2334,6 +2369,10 @@ public final class WFCMessage {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt32Size(15, historyMessage_);
|
||||
}
|
||||
if (((bitField0_ & 0x00008000) == 0x00008000)) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt32Size(16, superGroup_);
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
@@ -2480,6 +2519,8 @@ public final class WFCMessage {
|
||||
bitField0_ = (bitField0_ & ~0x00002000);
|
||||
historyMessage_ = 0;
|
||||
bitField0_ = (bitField0_ & ~0x00004000);
|
||||
superGroup_ = 0;
|
||||
bitField0_ = (bitField0_ & ~0x00008000);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -2568,6 +2609,10 @@ public final class WFCMessage {
|
||||
to_bitField0_ |= 0x00004000;
|
||||
}
|
||||
result.historyMessage_ = historyMessage_;
|
||||
if (((from_bitField0_ & 0x00008000) == 0x00008000)) {
|
||||
to_bitField0_ |= 0x00008000;
|
||||
}
|
||||
result.superGroup_ = superGroup_;
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
@@ -2639,6 +2684,9 @@ public final class WFCMessage {
|
||||
if (other.hasHistoryMessage()) {
|
||||
setHistoryMessage(other.getHistoryMessage());
|
||||
}
|
||||
if (other.hasSuperGroup()) {
|
||||
setSuperGroup(other.getSuperGroup());
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
}
|
||||
@@ -3374,6 +3422,39 @@ public final class WFCMessage {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -67224,179 +67305,180 @@ public final class WFCMessage {
|
||||
"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" +
|
||||
"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" +
|
||||
"\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_" +
|
||||
"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",
|
||||
"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" +
|
||||
"member_id\030\001 \002(\t\022\r\n\005alias\030\002 \001(\t\022\014\n\004type\030\003" +
|
||||
" \002(\005\022\021\n\tupdate_dt\030\004 \001(\003\022\021\n\tcreate_dt\030\005 \001" +
|
||||
"(\003\022\r\n\005extra\030\006 \001(\t\"F\n\005Group\022\036\n\ngroup_info" +
|
||||
"\030\001 \002(\0132\n.GroupInfo\022\035\n\007members\030\002 \003(\0132\014.Gr" +
|
||||
"oupMember\"\313\001\n\013ChannelMenu\022\014\n\004type\030\001 \002(\t\022" +
|
||||
"\014\n\004name\030\002 \002(\t\022\013\n\003key\030\003 \001(\t\022\013\n\003url\030\004 \001(\t\022" +
|
||||
"\020\n\010media_id\030\005 \001(\t\022\022\n\narticle_id\030\006 \001(\t\022\016\n" +
|
||||
"\006app_id\030\007 \001(\t\022\020\n\010app_page\030\010 \001(\t\022\036\n\010sub_m",
|
||||
"enu\030\t \003(\0132\014.ChannelMenu\022\017\n\007menu_id\030\n \001(\t" +
|
||||
"\022\r\n\005extra\030\013 \001(\t\"-\n\017ChannelMenuList\022\032\n\004me" +
|
||||
"nu\030\001 \003(\0132\014.ChannelMenu\"\340\001\n\013ChannelInfo\022\021" +
|
||||
"\n\ttarget_id\030\001 \001(\t\022\014\n\004name\030\002 \002(\t\022\020\n\010portr" +
|
||||
"ait\030\003 \001(\t\022\r\n\005owner\030\004 \001(\t\022\016\n\006status\030\005 \001(\005" +
|
||||
"\022\014\n\004desc\030\006 \001(\t\022\r\n\005extra\030\007 \001(\t\022\021\n\tupdate_" +
|
||||
"dt\030\010 \001(\003\022\016\n\006secret\030\t \001(\t\022\020\n\010callback\030\n \001" +
|
||||
"(\t\022\021\n\tautomatic\030\013 \001(\005\022\032\n\004menu\030\014 \003(\0132\014.Ch" +
|
||||
"annelMenu\"D\n\021ModifyChannelInfo\022\022\n\nchanne" +
|
||||
"l_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\r\n\005value\030\003 \002(\t\"",
|
||||
"8\n\017TransferChannel\022\022\n\nchannel_id\030\001 \002(\t\022\021" +
|
||||
"\n\tnew_owner\030\002 \002(\t\"3\n\017PullChannelInfo\022\022\n\n" +
|
||||
"channel_id\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"H\n\023PullCh" +
|
||||
"annelListener\022\022\n\nchannel_id\030\001 \002(\t\022\016\n\006off" +
|
||||
"set\030\002 \002(\005\022\r\n\005count\030\003 \002(\005\"R\n\031PullChannelL" +
|
||||
"istenerResult\022\023\n\013total_count\030\001 \002(\005\022\016\n\006of" +
|
||||
"fset\030\002 \002(\005\022\020\n\010listener\030\003 \003(\t\"3\n\rListenCh" +
|
||||
"annel\022\022\n\nchannel_id\030\001 \002(\t\022\016\n\006listen\030\002 \002(" +
|
||||
"\005\"E\n\023SearchChannelResult\022\035\n\007channel\030\001 \003(" +
|
||||
"\0132\014.ChannelInfo\022\017\n\007keyword\030\002 \002(\t\"\235\002\n\016Mes",
|
||||
"sageContent\022\014\n\004type\030\001 \002(\005\022\032\n\022searchable_" +
|
||||
"content\030\002 \001(\t\022\024\n\014push_content\030\003 \001(\t\022\017\n\007c" +
|
||||
"ontent\030\004 \001(\t\022\014\n\004data\030\005 \001(\014\022\021\n\tmediaType\030" +
|
||||
"\006 \001(\005\022\026\n\016remoteMediaUrl\030\007 \001(\t\022\024\n\014persist" +
|
||||
"_flag\030\010 \001(\005\022\027\n\017expire_duration\030\t \001(\005\022\026\n\016" +
|
||||
"mentioned_type\030\n \001(\005\022\030\n\020mentioned_target" +
|
||||
"\030\013 \003(\t\022\r\n\005extra\030\014 \001(\t\022\021\n\tpush_data\030\r \001(\t" +
|
||||
"\"\226\001\n\025AddGroupMemberRequest\022\020\n\010group_id\030\001" +
|
||||
" \002(\t\022\"\n\014added_member\030\002 \003(\0132\014.GroupMember" +
|
||||
"\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(",
|
||||
"\0132\017.MessageContent\022\r\n\005extra\030\005 \001(\t\"{\n\022Cre" +
|
||||
"ateGroupRequest\022\025\n\005group\030\001 \002(\0132\006.Group\022\017" +
|
||||
"\n\007to_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\0132" +
|
||||
"\017.MessageContent\022\024\n\014member_extra\030\004 \001(\t\"a" +
|
||||
"\n\023DismissGroupRequest\022\020\n\010group_id\030\001 \002(\t\022" +
|
||||
"\017\n\007to_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\013" +
|
||||
"2\017.MessageContent\"\245\001\n\rFriendRequest\022\020\n\010f" +
|
||||
"rom_uid\030\001 \001(\t\022\016\n\006to_uid\030\002 \002(\t\022\016\n\006reason\030" +
|
||||
"\003 \002(\t\022\016\n\006status\030\004 \001(\005\022\021\n\tupdate_dt\030\005 \001(\003" +
|
||||
"\022\030\n\020from_read_status\030\006 \001(\010\022\026\n\016to_read_st",
|
||||
"atus\030\007 \001(\010\022\r\n\005extra\030\010 \001(\t\"#\n\rGeneralResu" +
|
||||
"lt\022\022\n\nerror_code\030\001 \002(\005\"?\n\025GetUploadToken" +
|
||||
"Request\022\022\n\nmedia_type\030\001 \002(\005\022\022\n\nmedia_pat" +
|
||||
"h\030\002 \002(\t\"S\n\024GetUploadTokenResult\022\016\n\006domai" +
|
||||
"n\030\001 \002(\t\022\r\n\005token\030\002 \002(\t\022\016\n\006server\030\003 \002(\t\022\014" +
|
||||
"\n\004port\030\004 \001(\005\"H\n\023HandleFriendRequest\022\022\n\nt" +
|
||||
"arget_uid\030\001 \002(\t\022\016\n\006status\030\002 \002(\005\022\r\n\005extra" +
|
||||
"\030\003 \001(\t\"\023\n\005IDBuf\022\n\n\002id\030\001 \002(\t\"\027\n\tIDListBuf" +
|
||||
"\022\n\n\002id\030\001 \003(\t\"\256\001\n\007Message\022#\n\014conversation" +
|
||||
"\030\001 \002(\0132\r.Conversation\022\021\n\tfrom_user\030\002 \002(\t",
|
||||
"\022 \n\007content\030\003 \002(\0132\017.MessageContent\022\022\n\nme" +
|
||||
"ssage_id\030\004 \001(\003\022\030\n\020server_timestamp\030\005 \001(\003" +
|
||||
"\022\017\n\007to_user\030\006 \001(\t\022\n\n\002to\030\007 \003(\t\"\353\001\n\004User\022\013" +
|
||||
"\n\003uid\030\001 \002(\t\022\014\n\004name\030\002 \001(\t\022\024\n\014display_nam" +
|
||||
"e\030\003 \001(\t\022\020\n\010portrait\030\004 \001(\t\022\016\n\006mobile\030\005 \001(" +
|
||||
"\t\022\r\n\005email\030\006 \001(\t\022\017\n\007address\030\007 \001(\t\022\017\n\007com" +
|
||||
"pany\030\010 \001(\t\022\r\n\005extra\030\t \001(\t\022\021\n\tupdate_dt\030\n" +
|
||||
" \001(\003\022\016\n\006gender\030\013 \001(\005\022\016\n\006social\030\014 \001(\t\022\014\n\004" +
|
||||
"type\030\r \001(\005\022\017\n\007deleted\030\016 \001(\005\"c\n\005Robot\022\013\n\003" +
|
||||
"uid\030\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\r\n\005owner\030\003 \001(\t\022",
|
||||
"\016\n\006secret\030\004 \001(\t\022\020\n\010callback\030\005 \001(\t\022\r\n\005ext" +
|
||||
"ra\030\006 \001(\t\"(\n\017GetRobotsResult\022\025\n\005entry\030\001 \003" +
|
||||
"(\0132\006.Robot\"g\n\030UploadDeviceTokenRequest\022\020" +
|
||||
"\n\010platform\030\001 \002(\005\022\020\n\010app_name\030\002 \002(\t\022\024\n\014de" +
|
||||
"vice_token\030\003 \002(\t\022\021\n\tpush_type\030\004 \002(\005\"\201\001\n\026" +
|
||||
"ModifyGroupInfoRequest\022\020\n\010group_id\030\001 \002(\t" +
|
||||
"\022\014\n\004type\030\002 \002(\005\022\r\n\005value\030\003 \002(\t\022\017\n\007to_line" +
|
||||
"\030\004 \003(\005\022\'\n\016notify_content\030\005 \001(\0132\017.Message" +
|
||||
"Content\"\203\001\n\026SetGroupManagerRequest\022\020\n\010gr" +
|
||||
"oup_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\017\n\007user_id\030\003 ",
|
||||
"\003(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_content\030\005" +
|
||||
" \001(\0132\017.MessageContent\"(\n\tInfoEntry\022\014\n\004ty" +
|
||||
"pe\030\001 \002(\005\022\r\n\005value\030\002 \002(\t\"0\n\023ModifyMyInfoR" +
|
||||
"equest\022\031\n\005entry\030\001 \003(\0132\n.InfoEntry\";\n\rNot" +
|
||||
"ifyMessage\022\014\n\004type\030\001 \002(\005\022\014\n\004head\030\002 \002(\003\022\016" +
|
||||
"\n\006target\030\003 \001(\t\"=\n\022PullMessageRequest\022\n\n\002" +
|
||||
"id\030\001 \002(\003\022\014\n\004type\030\002 \002(\005\022\r\n\005delay\030\003 \001(\003\"M\n" +
|
||||
"\021PullMessageResult\022\031\n\007message\030\001 \003(\0132\010.Me" +
|
||||
"ssage\022\017\n\007current\030\002 \002(\003\022\014\n\004head\030\003 \002(\003\"/\n\023" +
|
||||
"PullGroupInfoResult\022\030\n\004info\030\001 \003(\0132\n.Grou",
|
||||
"pInfo\"6\n\026PullGroupMemberRequest\022\016\n\006targe" +
|
||||
"t\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"5\n\025PullGroupMember" +
|
||||
"Result\022\034\n\006member\030\001 \003(\0132\014.GroupMember\"-\n\013" +
|
||||
"UserRequest\022\013\n\003uid\030\001 \002(\t\022\021\n\tupdate_dt\030\002 " +
|
||||
"\001(\003\"0\n\017PullUserRequest\022\035\n\007request\030\001 \003(\0132" +
|
||||
"\014.UserRequest\"/\n\nUserResult\022\023\n\004user\030\001 \002(" +
|
||||
"\0132\005.User\022\014\n\004code\030\002 \002(\005\"-\n\016PullUserResult" +
|
||||
"\022\033\n\006result\030\001 \003(\0132\013.UserResult\"^\n\020QuitGro" +
|
||||
"upRequest\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002" +
|
||||
" \003(\005\022\'\n\016notify_content\030\003 \001(\0132\017.MessageCo",
|
||||
"ntent\"~\n\030RemoveGroupMemberRequest\022\020\n\010gro" +
|
||||
"up_id\030\001 \002(\t\022\026\n\016removed_member\030\002 \003(\t\022\017\n\007t" +
|
||||
"o_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.M" +
|
||||
"essageContent\"u\n\024TransferGroupRequest\022\020\n" +
|
||||
"\010group_id\030\001 \002(\t\022\021\n\tnew_owner\030\002 \002(\t\022\017\n\007to" +
|
||||
"_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Me" +
|
||||
"ssageContent\"\206\001\n\026ModifyGroupMemberAlias\022" +
|
||||
"\020\n\010group_id\030\001 \002(\t\022\r\n\005alias\030\002 \002(\t\022\017\n\007to_l" +
|
||||
"ine\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Mess" +
|
||||
"ageContent\022\021\n\tmember_id\030\005 \001(\t\"\206\001\n\026Modify",
|
||||
"GroupMemberExtra\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to" +
|
||||
"_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\0132\017.Me" +
|
||||
"ssageContent\022\r\n\005extra\030\004 \001(\t\022\021\n\tmember_id" +
|
||||
"\030\005 \001(\t\"P\n\020UserSettingEntry\022\r\n\005scope\030\001 \002(" +
|
||||
"\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\022\021\n\tupdate_" +
|
||||
"dt\030\004 \002(\003\"A\n\024ModifyUserSettingReq\022\r\n\005scop" +
|
||||
"e\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\"\032\n\007V" +
|
||||
"ersion\022\017\n\007version\030\001 \002(\003\"8\n\024GetUserSettin" +
|
||||
"gResult\022 \n\005entry\030\001 \003(\0132\021.UserSettingEntr" +
|
||||
"y\"f\n\006Friend\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030\002 \002(\005\022",
|
||||
"\021\n\tupdate_dt\030\003 \002(\003\022\r\n\005alias\030\004 \001(\t\022\017\n\007bla" +
|
||||
"cked\030\005 \001(\005\022\r\n\005extra\030\006 \001(\t\"*\n\020GetFriendsR" +
|
||||
"esult\022\026\n\005entry\030\001 \003(\0132\007.Friend\"7\n\026GetFrie" +
|
||||
"ndRequestResult\022\035\n\005entry\030\001 \003(\0132\016.FriendR" +
|
||||
"equest\"\243\001\n\021ConnectAckPayload\022\020\n\010msg_head" +
|
||||
"\030\001 \001(\003\022\023\n\013friend_head\030\002 \001(\003\022\026\n\016friend_rq" +
|
||||
"_head\030\003 \001(\003\022\024\n\014setting_head\030\004 \001(\003\022\021\n\tnod" +
|
||||
"e_addr\030\005 \001(\t\022\021\n\tnode_port\030\006 \001(\005\022\023\n\013serve" +
|
||||
"r_time\030\007 \001(\003\"P\n\rIMHttpWrapper\022\r\n\005token\030\001" +
|
||||
" \002(\t\022\021\n\tclient_id\030\002 \002(\t\022\017\n\007request\030\003 \002(\t",
|
||||
"\022\014\n\004data\030\004 \001(\014\"A\n\021SearchUserRequest\022\017\n\007k" +
|
||||
"eyword\030\001 \002(\t\022\r\n\005fuzzy\030\002 \001(\005\022\014\n\004page\030\003 \001(" +
|
||||
"\005\"(\n\020SearchUserResult\022\024\n\005entry\030\001 \003(\0132\005.U" +
|
||||
"ser\"@\n\026GetChatroomInfoRequest\022\023\n\013chatroo" +
|
||||
"m_id\030\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"\227\001\n\014Chatro" +
|
||||
"omInfo\022\r\n\005title\030\001 \002(\t\022\014\n\004desc\030\002 \001(\t\022\020\n\010p" +
|
||||
"ortrait\030\003 \001(\t\022\024\n\014member_count\030\004 \001(\005\022\021\n\tc" +
|
||||
"reate_dt\030\005 \001(\003\022\021\n\tupdate_dt\030\006 \001(\003\022\r\n\005ext" +
|
||||
"ra\030\007 \001(\t\022\r\n\005state\030\010 \001(\005\"F\n\034GetChatroomMe" +
|
||||
"mberInfoRequest\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\t",
|
||||
"max_count\030\002 \001(\005\";\n\022ChatroomMemberInfo\022\024\n" +
|
||||
"\014member_count\030\001 \001(\005\022\017\n\007members\030\002 \003(\t\"\026\n\010" +
|
||||
"INT64Buf\022\n\n\002id\030\001 \002(\003\"4\n\023NotifyRecallMess" +
|
||||
"age\022\n\n\002id\030\001 \002(\003\022\021\n\tfrom_user\030\002 \002(\t\"/\n\020Bl" +
|
||||
"ackUserRequest\022\013\n\003uid\030\001 \002(\t\022\016\n\006status\030\002 " +
|
||||
"\002(\005\"\323\001\n\014RouteRequest\022\013\n\003app\030\001 \001(\t\022\020\n\010pla" +
|
||||
"tform\030\002 \001(\005\022\021\n\tpush_type\030\003 \001(\005\022\023\n\013device" +
|
||||
"_name\030\004 \001(\t\022\026\n\016device_version\030\005 \001(\t\022\022\n\np" +
|
||||
"hone_name\030\006 \001(\t\022\020\n\010language\030\007 \001(\t\022\024\n\014car" +
|
||||
"rier_name\030\010 \001(\t\022\023\n\013app_version\030\t \001(\t\022\023\n\013",
|
||||
"sdk_version\030\n \001(\t\"D\n\rRouteResponse\022\014\n\004ho" +
|
||||
"st\030\001 \002(\t\022\021\n\tlong_port\030\002 \002(\005\022\022\n\nshort_por" +
|
||||
"t\030\003 \002(\005\"G\n\017GetTokenRequest\022\017\n\007user_id\030\001 " +
|
||||
"\002(\t\022\021\n\tclient_id\030\002 \002(\t\022\020\n\010platform\030\003 \001(\005" +
|
||||
"\"r\n\022LoadRemoteMessages\022#\n\014conversation\030\001" +
|
||||
" \002(\0132\r.Conversation\022\022\n\nbefore_uid\030\002 \002(\003\022" +
|
||||
"\r\n\005count\030\003 \002(\005\022\024\n\014content_type\030\004 \003(\005\"a\n\020" +
|
||||
"MultiCastMessage\022\021\n\tfrom_user\030\001 \002(\t\022 \n\007c" +
|
||||
"ontent\030\002 \002(\0132\017.MessageContent\022\n\n\002to\030\003 \003(" +
|
||||
"\t\022\014\n\004line\030\004 \002(\005\"E\n\035RecallMultiCastMessag",
|
||||
"eRequest\022\022\n\nmessage_id\030\001 \002(\003\022\020\n\010receiver" +
|
||||
"\030\002 \003(\t\"@\n\017AuthCodeRequest\022\021\n\ttarget_id\030\001" +
|
||||
" \002(\t\022\014\n\004type\030\002 \002(\005\022\014\n\004host\030\003 \002(\t\"o\n\030Appl" +
|
||||
"icationConfigRequest\022\r\n\005appId\030\001 \002(\t\022\017\n\007a" +
|
||||
"ppType\030\002 \002(\005\022\021\n\ttimestamp\030\003 \002(\003\022\r\n\005nonce" +
|
||||
"\030\004 \002(\t\022\021\n\tsignature\030\005 \002(\tB#\n\025cn.wildfire" +
|
||||
"chat.protoB\nWFCMessage"
|
||||
"history_message\030\017 \001(\005\022\023\n\013super_group\030\020 \001" +
|
||||
"(\005\"r\n\013GroupMember\022\021\n\tmember_id\030\001 \002(\t\022\r\n\005" +
|
||||
"alias\030\002 \001(\t\022\014\n\004type\030\003 \002(\005\022\021\n\tupdate_dt\030\004" +
|
||||
" \001(\003\022\021\n\tcreate_dt\030\005 \001(\003\022\r\n\005extra\030\006 \001(\t\"F" +
|
||||
"\n\005Group\022\036\n\ngroup_info\030\001 \002(\0132\n.GroupInfo\022" +
|
||||
"\035\n\007members\030\002 \003(\0132\014.GroupMember\"\313\001\n\013Chann" +
|
||||
"elMenu\022\014\n\004type\030\001 \002(\t\022\014\n\004name\030\002 \002(\t\022\013\n\003ke" +
|
||||
"y\030\003 \001(\t\022\013\n\003url\030\004 \001(\t\022\020\n\010media_id\030\005 \001(\t\022\022" +
|
||||
"\n\narticle_id\030\006 \001(\t\022\016\n\006app_id\030\007 \001(\t\022\020\n\010ap",
|
||||
"p_page\030\010 \001(\t\022\036\n\010sub_menu\030\t \003(\0132\014.Channel" +
|
||||
"Menu\022\017\n\007menu_id\030\n \001(\t\022\r\n\005extra\030\013 \001(\t\"-\n\017" +
|
||||
"ChannelMenuList\022\032\n\004menu\030\001 \003(\0132\014.ChannelM" +
|
||||
"enu\"\340\001\n\013ChannelInfo\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\016\n\006status\030\005 \001(\005\022\014\n\004desc\030\006 \001(\t\022\r\n\005e" +
|
||||
"xtra\030\007 \001(\t\022\021\n\tupdate_dt\030\010 \001(\003\022\016\n\006secret\030" +
|
||||
"\t \001(\t\022\020\n\010callback\030\n \001(\t\022\021\n\tautomatic\030\013 \001" +
|
||||
"(\005\022\032\n\004menu\030\014 \003(\0132\014.ChannelMenu\"D\n\021Modify" +
|
||||
"ChannelInfo\022\022\n\nchannel_id\030\001 \002(\t\022\014\n\004type\030",
|
||||
"\002 \002(\005\022\r\n\005value\030\003 \002(\t\"8\n\017TransferChannel\022" +
|
||||
"\022\n\nchannel_id\030\001 \002(\t\022\021\n\tnew_owner\030\002 \002(\t\"3" +
|
||||
"\n\017PullChannelInfo\022\022\n\nchannel_id\030\001 \002(\t\022\014\n" +
|
||||
"\004head\030\002 \002(\003\"H\n\023PullChannelListener\022\022\n\nch" +
|
||||
"annel_id\030\001 \002(\t\022\016\n\006offset\030\002 \002(\005\022\r\n\005count\030" +
|
||||
"\003 \002(\005\"R\n\031PullChannelListenerResult\022\023\n\013to" +
|
||||
"tal_count\030\001 \002(\005\022\016\n\006offset\030\002 \002(\005\022\020\n\010liste" +
|
||||
"ner\030\003 \003(\t\"3\n\rListenChannel\022\022\n\nchannel_id" +
|
||||
"\030\001 \002(\t\022\016\n\006listen\030\002 \002(\005\"E\n\023SearchChannelR" +
|
||||
"esult\022\035\n\007channel\030\001 \003(\0132\014.ChannelInfo\022\017\n\007",
|
||||
"keyword\030\002 \002(\t\"\235\002\n\016MessageContent\022\014\n\004type" +
|
||||
"\030\001 \002(\005\022\032\n\022searchable_content\030\002 \001(\t\022\024\n\014pu" +
|
||||
"sh_content\030\003 \001(\t\022\017\n\007content\030\004 \001(\t\022\014\n\004dat" +
|
||||
"a\030\005 \001(\014\022\021\n\tmediaType\030\006 \001(\005\022\026\n\016remoteMedi" +
|
||||
"aUrl\030\007 \001(\t\022\024\n\014persist_flag\030\010 \001(\005\022\027\n\017expi" +
|
||||
"re_duration\030\t \001(\005\022\026\n\016mentioned_type\030\n \001(" +
|
||||
"\005\022\030\n\020mentioned_target\030\013 \003(\t\022\r\n\005extra\030\014 \001" +
|
||||
"(\t\022\021\n\tpush_data\030\r \001(\t\"\226\001\n\025AddGroupMember" +
|
||||
"Request\022\020\n\010group_id\030\001 \002(\t\022\"\n\014added_membe" +
|
||||
"r\030\002 \003(\0132\014.GroupMember\022\017\n\007to_line\030\003 \003(\005\022\'",
|
||||
"\n\016notify_content\030\004 \001(\0132\017.MessageContent\022" +
|
||||
"\r\n\005extra\030\005 \001(\t\"{\n\022CreateGroupRequest\022\025\n\005" +
|
||||
"group\030\001 \002(\0132\006.Group\022\017\n\007to_line\030\002 \003(\005\022\'\n\016" +
|
||||
"notify_content\030\003 \001(\0132\017.MessageContent\022\024\n" +
|
||||
"\014member_extra\030\004 \001(\t\"a\n\023DismissGroupReque" +
|
||||
"st\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n" +
|
||||
"\016notify_content\030\003 \001(\0132\017.MessageContent\"\245" +
|
||||
"\001\n\rFriendRequest\022\020\n\010from_uid\030\001 \001(\t\022\016\n\006to" +
|
||||
"_uid\030\002 \002(\t\022\016\n\006reason\030\003 \002(\t\022\016\n\006status\030\004 \001" +
|
||||
"(\005\022\021\n\tupdate_dt\030\005 \001(\003\022\030\n\020from_read_statu",
|
||||
"s\030\006 \001(\010\022\026\n\016to_read_status\030\007 \001(\010\022\r\n\005extra" +
|
||||
"\030\010 \001(\t\"#\n\rGeneralResult\022\022\n\nerror_code\030\001 " +
|
||||
"\002(\005\"?\n\025GetUploadTokenRequest\022\022\n\nmedia_ty" +
|
||||
"pe\030\001 \002(\005\022\022\n\nmedia_path\030\002 \002(\t\"S\n\024GetUploa" +
|
||||
"dTokenResult\022\016\n\006domain\030\001 \002(\t\022\r\n\005token\030\002 " +
|
||||
"\002(\t\022\016\n\006server\030\003 \002(\t\022\014\n\004port\030\004 \001(\005\"H\n\023Han" +
|
||||
"dleFriendRequest\022\022\n\ntarget_uid\030\001 \002(\t\022\016\n\006" +
|
||||
"status\030\002 \002(\005\022\r\n\005extra\030\003 \001(\t\"\023\n\005IDBuf\022\n\n\002" +
|
||||
"id\030\001 \002(\t\"\027\n\tIDListBuf\022\n\n\002id\030\001 \003(\t\"\256\001\n\007Me" +
|
||||
"ssage\022#\n\014conversation\030\001 \002(\0132\r.Conversati",
|
||||
"on\022\021\n\tfrom_user\030\002 \002(\t\022 \n\007content\030\003 \002(\0132\017" +
|
||||
".MessageContent\022\022\n\nmessage_id\030\004 \001(\003\022\030\n\020s" +
|
||||
"erver_timestamp\030\005 \001(\003\022\017\n\007to_user\030\006 \001(\t\022\n" +
|
||||
"\n\002to\030\007 \003(\t\"\353\001\n\004User\022\013\n\003uid\030\001 \002(\t\022\014\n\004name" +
|
||||
"\030\002 \001(\t\022\024\n\014display_name\030\003 \001(\t\022\020\n\010portrait" +
|
||||
"\030\004 \001(\t\022\016\n\006mobile\030\005 \001(\t\022\r\n\005email\030\006 \001(\t\022\017\n" +
|
||||
"\007address\030\007 \001(\t\022\017\n\007company\030\010 \001(\t\022\r\n\005extra" +
|
||||
"\030\t \001(\t\022\021\n\tupdate_dt\030\n \001(\003\022\016\n\006gender\030\013 \001(" +
|
||||
"\005\022\016\n\006social\030\014 \001(\t\022\014\n\004type\030\r \001(\005\022\017\n\007delet" +
|
||||
"ed\030\016 \001(\005\"c\n\005Robot\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030",
|
||||
"\002 \002(\005\022\r\n\005owner\030\003 \001(\t\022\016\n\006secret\030\004 \001(\t\022\020\n\010" +
|
||||
"callback\030\005 \001(\t\022\r\n\005extra\030\006 \001(\t\"(\n\017GetRobo" +
|
||||
"tsResult\022\025\n\005entry\030\001 \003(\0132\006.Robot\"g\n\030Uploa" +
|
||||
"dDeviceTokenRequest\022\020\n\010platform\030\001 \002(\005\022\020\n" +
|
||||
"\010app_name\030\002 \002(\t\022\024\n\014device_token\030\003 \002(\t\022\021\n" +
|
||||
"\tpush_type\030\004 \002(\005\"\201\001\n\026ModifyGroupInfoRequ" +
|
||||
"est\022\020\n\010group_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\r\n\005v" +
|
||||
"alue\030\003 \002(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_co" +
|
||||
"ntent\030\005 \001(\0132\017.MessageContent\"\203\001\n\026SetGrou" +
|
||||
"pManagerRequest\022\020\n\010group_id\030\001 \002(\t\022\014\n\004typ",
|
||||
"e\030\002 \002(\005\022\017\n\007user_id\030\003 \003(\t\022\017\n\007to_line\030\004 \003(" +
|
||||
"\005\022\'\n\016notify_content\030\005 \001(\0132\017.MessageConte" +
|
||||
"nt\"(\n\tInfoEntry\022\014\n\004type\030\001 \002(\005\022\r\n\005value\030\002" +
|
||||
" \002(\t\"0\n\023ModifyMyInfoRequest\022\031\n\005entry\030\001 \003" +
|
||||
"(\0132\n.InfoEntry\";\n\rNotifyMessage\022\014\n\004type\030" +
|
||||
"\001 \002(\005\022\014\n\004head\030\002 \002(\003\022\016\n\006target\030\003 \001(\t\"=\n\022P" +
|
||||
"ullMessageRequest\022\n\n\002id\030\001 \002(\003\022\014\n\004type\030\002 " +
|
||||
"\002(\005\022\r\n\005delay\030\003 \001(\003\"M\n\021PullMessageResult\022" +
|
||||
"\031\n\007message\030\001 \003(\0132\010.Message\022\017\n\007current\030\002 " +
|
||||
"\002(\003\022\014\n\004head\030\003 \002(\003\"/\n\023PullGroupInfoResult",
|
||||
"\022\030\n\004info\030\001 \003(\0132\n.GroupInfo\"6\n\026PullGroupM" +
|
||||
"emberRequest\022\016\n\006target\030\001 \002(\t\022\014\n\004head\030\002 \002" +
|
||||
"(\003\"5\n\025PullGroupMemberResult\022\034\n\006member\030\001 " +
|
||||
"\003(\0132\014.GroupMember\"-\n\013UserRequest\022\013\n\003uid\030" +
|
||||
"\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"0\n\017PullUserRequ" +
|
||||
"est\022\035\n\007request\030\001 \003(\0132\014.UserRequest\"/\n\nUs" +
|
||||
"erResult\022\023\n\004user\030\001 \002(\0132\005.User\022\014\n\004code\030\002 " +
|
||||
"\002(\005\"-\n\016PullUserResult\022\033\n\006result\030\001 \003(\0132\013." +
|
||||
"UserResult\"^\n\020QuitGroupRequest\022\020\n\010group_" +
|
||||
"id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n\016notify_cont",
|
||||
"ent\030\003 \001(\0132\017.MessageContent\"~\n\030RemoveGrou" +
|
||||
"pMemberRequest\022\020\n\010group_id\030\001 \002(\t\022\026\n\016remo" +
|
||||
"ved_member\030\002 \003(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016not" +
|
||||
"ify_content\030\004 \001(\0132\017.MessageContent\"u\n\024Tr" +
|
||||
"ansferGroupRequest\022\020\n\010group_id\030\001 \002(\t\022\021\n\t" +
|
||||
"new_owner\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016noti" +
|
||||
"fy_content\030\004 \001(\0132\017.MessageContent\"\206\001\n\026Mo" +
|
||||
"difyGroupMemberAlias\022\020\n\010group_id\030\001 \002(\t\022\r" +
|
||||
"\n\005alias\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify" +
|
||||
"_content\030\004 \001(\0132\017.MessageContent\022\021\n\tmembe",
|
||||
"r_id\030\005 \001(\t\"\206\001\n\026ModifyGroupMemberExtra\022\020\n" +
|
||||
"\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n\016noti" +
|
||||
"fy_content\030\003 \001(\0132\017.MessageContent\022\r\n\005ext" +
|
||||
"ra\030\004 \001(\t\022\021\n\tmember_id\030\005 \001(\t\"P\n\020UserSetti" +
|
||||
"ngEntry\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005v" +
|
||||
"alue\030\003 \002(\t\022\021\n\tupdate_dt\030\004 \002(\003\"A\n\024ModifyU" +
|
||||
"serSettingReq\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(" +
|
||||
"\t\022\r\n\005value\030\003 \002(\t\"\032\n\007Version\022\017\n\007version\030\001" +
|
||||
" \002(\003\"8\n\024GetUserSettingResult\022 \n\005entry\030\001 " +
|
||||
"\003(\0132\021.UserSettingEntry\"f\n\006Friend\022\013\n\003uid\030",
|
||||
"\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\021\n\tupdate_dt\030\003 \002(\003\022" +
|
||||
"\r\n\005alias\030\004 \001(\t\022\017\n\007blacked\030\005 \001(\005\022\r\n\005extra" +
|
||||
"\030\006 \001(\t\"*\n\020GetFriendsResult\022\026\n\005entry\030\001 \003(" +
|
||||
"\0132\007.Friend\"7\n\026GetFriendRequestResult\022\035\n\005" +
|
||||
"entry\030\001 \003(\0132\016.FriendRequest\"\243\001\n\021ConnectA" +
|
||||
"ckPayload\022\020\n\010msg_head\030\001 \001(\003\022\023\n\013friend_he" +
|
||||
"ad\030\002 \001(\003\022\026\n\016friend_rq_head\030\003 \001(\003\022\024\n\014sett" +
|
||||
"ing_head\030\004 \001(\003\022\021\n\tnode_addr\030\005 \001(\t\022\021\n\tnod" +
|
||||
"e_port\030\006 \001(\005\022\023\n\013server_time\030\007 \001(\003\"P\n\rIMH" +
|
||||
"ttpWrapper\022\r\n\005token\030\001 \002(\t\022\021\n\tclient_id\030\002",
|
||||
" \002(\t\022\017\n\007request\030\003 \002(\t\022\014\n\004data\030\004 \001(\014\"A\n\021S" +
|
||||
"earchUserRequest\022\017\n\007keyword\030\001 \002(\t\022\r\n\005fuz" +
|
||||
"zy\030\002 \001(\005\022\014\n\004page\030\003 \001(\005\"(\n\020SearchUserResu" +
|
||||
"lt\022\024\n\005entry\030\001 \003(\0132\005.User\"@\n\026GetChatroomI" +
|
||||
"nfoRequest\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\tupdat" +
|
||||
"e_dt\030\002 \001(\003\"\227\001\n\014ChatroomInfo\022\r\n\005title\030\001 \002" +
|
||||
"(\t\022\014\n\004desc\030\002 \001(\t\022\020\n\010portrait\030\003 \001(\t\022\024\n\014me" +
|
||||
"mber_count\030\004 \001(\005\022\021\n\tcreate_dt\030\005 \001(\003\022\021\n\tu" +
|
||||
"pdate_dt\030\006 \001(\003\022\r\n\005extra\030\007 \001(\t\022\r\n\005state\030\010" +
|
||||
" \001(\005\"F\n\034GetChatroomMemberInfoRequest\022\023\n\013",
|
||||
"chatroom_id\030\001 \002(\t\022\021\n\tmax_count\030\002 \001(\005\";\n\022" +
|
||||
"ChatroomMemberInfo\022\024\n\014member_count\030\001 \001(\005" +
|
||||
"\022\017\n\007members\030\002 \003(\t\"\026\n\010INT64Buf\022\n\n\002id\030\001 \002(" +
|
||||
"\003\"4\n\023NotifyRecallMessage\022\n\n\002id\030\001 \002(\003\022\021\n\t" +
|
||||
"from_user\030\002 \002(\t\"/\n\020BlackUserRequest\022\013\n\003u" +
|
||||
"id\030\001 \002(\t\022\016\n\006status\030\002 \002(\005\"\323\001\n\014RouteReques" +
|
||||
"t\022\013\n\003app\030\001 \001(\t\022\020\n\010platform\030\002 \001(\005\022\021\n\tpush" +
|
||||
"_type\030\003 \001(\005\022\023\n\013device_name\030\004 \001(\t\022\026\n\016devi" +
|
||||
"ce_version\030\005 \001(\t\022\022\n\nphone_name\030\006 \001(\t\022\020\n\010" +
|
||||
"language\030\007 \001(\t\022\024\n\014carrier_name\030\010 \001(\t\022\023\n\013",
|
||||
"app_version\030\t \001(\t\022\023\n\013sdk_version\030\n \001(\t\"D" +
|
||||
"\n\rRouteResponse\022\014\n\004host\030\001 \002(\t\022\021\n\tlong_po" +
|
||||
"rt\030\002 \002(\005\022\022\n\nshort_port\030\003 \002(\005\"G\n\017GetToken" +
|
||||
"Request\022\017\n\007user_id\030\001 \002(\t\022\021\n\tclient_id\030\002 " +
|
||||
"\002(\t\022\020\n\010platform\030\003 \001(\005\"r\n\022LoadRemoteMessa" +
|
||||
"ges\022#\n\014conversation\030\001 \002(\0132\r.Conversation" +
|
||||
"\022\022\n\nbefore_uid\030\002 \002(\003\022\r\n\005count\030\003 \002(\005\022\024\n\014c" +
|
||||
"ontent_type\030\004 \003(\005\"a\n\020MultiCastMessage\022\021\n" +
|
||||
"\tfrom_user\030\001 \002(\t\022 \n\007content\030\002 \002(\0132\017.Mess" +
|
||||
"ageContent\022\n\n\002to\030\003 \003(\t\022\014\n\004line\030\004 \002(\005\"E\n\035",
|
||||
"RecallMultiCastMessageRequest\022\022\n\nmessage" +
|
||||
"_id\030\001 \002(\003\022\020\n\010receiver\030\002 \003(\t\"@\n\017AuthCodeR" +
|
||||
"equest\022\021\n\ttarget_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022" +
|
||||
"\014\n\004host\030\003 \002(\t\"o\n\030ApplicationConfigReques" +
|
||||
"t\022\r\n\005appId\030\001 \002(\t\022\017\n\007appType\030\002 \002(\005\022\021\n\ttim" +
|
||||
"estamp\030\003 \002(\003\022\r\n\005nonce\030\004 \002(\t\022\021\n\tsignature" +
|
||||
"\030\005 \002(\tB/\n\025cn.wildfirechat.protoB\nWFCMess" +
|
||||
"ageZ\n./go;proto"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||
@@ -67420,7 +67502,7 @@ public final class WFCMessage {
|
||||
internal_static_GroupInfo_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
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 =
|
||||
getDescriptor().getMessageTypes().get(3);
|
||||
internal_static_GroupMember_fieldAccessorTable = new
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
@@ -18,38 +19,46 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
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 void init(byte[] secret) {
|
||||
if (secret != null && secret.length == 16) {
|
||||
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 int keyLen = 16;
|
||||
private final static int ivLen = 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};
|
||||
|
||||
public static byte[] AESEncrypt(String sSrc, String 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) {
|
||||
if (aesKey == null) {
|
||||
System.out.print("Key为空null");
|
||||
return null;
|
||||
}
|
||||
// 判断Key是否为16位
|
||||
if (aesKey.length != 16) {
|
||||
if (aesKey.length < keyLen) {
|
||||
System.out.print("Key长度不是16位");
|
||||
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 {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
|
||||
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);
|
||||
|
||||
//2018.1.1 0:0:0 以来的小时数
|
||||
@@ -101,21 +110,26 @@ public class AES {
|
||||
}
|
||||
|
||||
private static byte[] convertUserKey(String userKey) {
|
||||
byte[] key = new byte[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
byte[] key = new byte[keyLen];
|
||||
for (int i = 0; i < keyLen; i++) {
|
||||
key[i] = (byte) (userKey.charAt(i) & 0xFF);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
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;
|
||||
if (userKey != null && !userKey.isEmpty()) {
|
||||
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 {
|
||||
|
||||
// 判断Key是否正确
|
||||
@@ -123,14 +137,25 @@ public class AES {
|
||||
aesKey = aes_key;
|
||||
}
|
||||
// 判断Key是否为16位
|
||||
if (aesKey.length != 16) {
|
||||
if (aesKey.length < keyLen) {
|
||||
System.out.print("Key长度不是16位");
|
||||
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");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
IvParameterSpec iv = new IvParameterSpec(aesKey);
|
||||
IvParameterSpec iv = new IvParameterSpec(ivKeys);
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
|
||||
try {
|
||||
byte[] original = cipher.doFinal(sSrc);
|
||||
@@ -152,6 +177,9 @@ public class AES {
|
||||
int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
|
||||
|
||||
if (curhour - hours > 24 && checkTime) {
|
||||
if(invalidTime != null) {
|
||||
invalidTime[0] = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
byte[] neworiginal = new byte[original.length - 4];
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!--<relativePath>../pom.xml</relativePath>-->
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.97</version>
|
||||
<version>1.1.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>distribution</artifactId>
|
||||
@@ -130,73 +130,70 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- 打包RPM 开始-->
|
||||
<!-- 打包RPM 包需要本地有rpm命令才可以,linux和mac都可以安装rpm。如果是windows需要cygwin安装rpm才可以,如果不需要rpm包,可以把这个plugin注释掉-->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>rpm-maven-plugin</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-rpm</id>
|
||||
<goals>
|
||||
<goal>rpm</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
<configuration>
|
||||
<group>Applications/Chat</group>
|
||||
<name>im-server</name>
|
||||
<needarch>noarch</needarch>
|
||||
<targetOS>linux</targetOS>
|
||||
<prefix>/opt/im-server</prefix>
|
||||
<defineStatements>
|
||||
<defineStatement>_unpackaged_files_terminate_build 0</defineStatement>
|
||||
</defineStatements>
|
||||
<copyTo>
|
||||
target/im-server-${project.version}.rpm
|
||||
</copyTo>
|
||||
<requires>
|
||||
<require>java-1.8.0-openjdk-headless</require>
|
||||
</requires>
|
||||
|
||||
<mappings>
|
||||
<mapping>
|
||||
<directory>/opt/im-server</directory>
|
||||
<filemode>755</filemode>
|
||||
<sources>
|
||||
<source>
|
||||
<location>${project.build.directory}/distribution-${project.version}-bundle-tar.tar.gz</location>
|
||||
</source>
|
||||
</sources>
|
||||
</mapping>
|
||||
|
||||
<mapping>
|
||||
<directory>/usr/lib/systemd/system</directory>
|
||||
<filemode>644</filemode>
|
||||
<username>root</username>
|
||||
<groupname>root</groupname>
|
||||
<directoryIncluded>false</directoryIncluded>
|
||||
<sources>
|
||||
<source>
|
||||
<location>${project.basedir}/../systemd/im-server.service</location>
|
||||
</source>
|
||||
</sources>
|
||||
</mapping>
|
||||
</mappings>
|
||||
<postinstallScriptlet>
|
||||
<scriptFile>${project.basedir}/src/main/rpm/install.sh</scriptFile>
|
||||
<fileEncoding>utf-8</fileEncoding>
|
||||
<filter>true</filter>
|
||||
</postinstallScriptlet>
|
||||
<postremoveScriptlet>
|
||||
<scriptFile>${project.basedir}/src/main/rpm/uninstall.sh</scriptFile>
|
||||
<fileEncoding>utf-8</fileEncoding>
|
||||
<filter>true</filter>
|
||||
</postremoveScriptlet>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 打包RPM插件,如果需要打包RPM格式请打开下面注释 -->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.codehaus.mojo</groupId>-->
|
||||
<!-- <artifactId>rpm-maven-plugin</artifactId>-->
|
||||
<!-- <version>2.2.0</version>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>generate-rpm</id>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>rpm</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <group>Applications/Chat</group>-->
|
||||
<!-- <name>im-server</name>-->
|
||||
<!-- <needarch>noarch</needarch>-->
|
||||
<!-- <targetOS>linux</targetOS>-->
|
||||
<!-- <prefix>/opt/im-server</prefix>-->
|
||||
<!-- <defineStatements>-->
|
||||
<!-- <defineStatement>_unpackaged_files_terminate_build 0</defineStatement>-->
|
||||
<!-- </defineStatements>-->
|
||||
<!-- <copyTo>-->
|
||||
<!-- target/im-server-${project.version}.rpm-->
|
||||
<!-- </copyTo>-->
|
||||
<!-- <requires>-->
|
||||
<!-- <require>java-1.8.0-openjdk-headless</require>-->
|
||||
<!-- </requires>-->
|
||||
<!-- <mappings>-->
|
||||
<!-- <mapping>-->
|
||||
<!-- <directory>/opt/im-server</directory>-->
|
||||
<!-- <filemode>755</filemode>-->
|
||||
<!-- <sources>-->
|
||||
<!-- <source>-->
|
||||
<!-- <location>${project.build.directory}/distribution-${project.version}-bundle-tar.tar.gz</location>-->
|
||||
<!-- </source>-->
|
||||
<!-- </sources>-->
|
||||
<!-- </mapping>-->
|
||||
<!-- <mapping>-->
|
||||
<!-- <directory>/usr/lib/systemd/system</directory>-->
|
||||
<!-- <filemode>644</filemode>-->
|
||||
<!-- <username>root</username>-->
|
||||
<!-- <groupname>root</groupname>-->
|
||||
<!-- <directoryIncluded>false</directoryIncluded>-->
|
||||
<!-- <sources>-->
|
||||
<!-- <source>-->
|
||||
<!-- <location>${project.basedir}/../systemd/im-server.service</location>-->
|
||||
<!-- </source>-->
|
||||
<!-- </sources>-->
|
||||
<!-- </mapping>-->
|
||||
<!-- </mappings>-->
|
||||
<!-- <postinstallScriptlet>-->
|
||||
<!-- <scriptFile>${project.basedir}/src/main/rpm/install.sh</scriptFile>-->
|
||||
<!-- <fileEncoding>utf-8</fileEncoding>-->
|
||||
<!-- <filter>true</filter>-->
|
||||
<!-- </postinstallScriptlet>-->
|
||||
<!-- <postremoveScriptlet>-->
|
||||
<!-- <scriptFile>${project.basedir}/src/main/rpm/uninstall.sh</scriptFile>-->
|
||||
<!-- <fileEncoding>utf-8</fileEncoding>-->
|
||||
<!-- <filter>true</filter>-->
|
||||
<!-- </postremoveScriptlet>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- 打包RPM 结束-->
|
||||
|
||||
</plugins>
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
<directory>../systemd/</directory>
|
||||
<outputDirectory>/systemd</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>src/main/checker/</directory>
|
||||
<outputDirectory>checker/</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
||||
<files>
|
||||
@@ -39,6 +44,12 @@
|
||||
<fileMode>0755</fileMode>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>src/main/scripts/stop.sh</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<fileMode>0755</fileMode>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>src/main/scripts/wildfirechat.bat</source>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
@@ -49,7 +60,7 @@
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>src/main/files/release_note.md</source>
|
||||
<source>../release_note.md</source>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
@@ -75,8 +86,22 @@
|
||||
<outputDirectory>server_sdk/</outputDirectory>
|
||||
<destName>common-${project.version}.jar</destName>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
<file>
|
||||
<source>../sdk/target/checker.jar</source>
|
||||
<outputDirectory>checker/</outputDirectory>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>../docker/Dockerfile</source>
|
||||
<outputDirectory>docker/</outputDirectory>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>../docker/README.md</source>
|
||||
<outputDirectory>docker/</outputDirectory>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
部署IM服务后,可以使用Server SDK通过API来检查服务的部署情况,可以执行:
|
||||
```shell
|
||||
java -jar checker.jar http://127.0.0.1:18080 123456 http://127.0.0.1 true false
|
||||
```
|
||||
来检查。检查之后会产生垃圾数据,请在检查之后停掉IM服务后,再删除掉IM服务数据库。此检查仅检查API,检查通过并不代表部署肯定成功,还需要客户端来验证。
|
||||
@@ -8,8 +8,13 @@ if [ ! -d /etc/im-server ]; then
|
||||
mkdir /etc/im-server
|
||||
fi
|
||||
|
||||
if [ ! -d /var/log/im-server ]; then
|
||||
mkdir /var/log/im-server
|
||||
fi
|
||||
|
||||
mv -f /opt/im-server/config /etc/im-server
|
||||
systemctl daemon-reload
|
||||
|
||||
echo "IM server folders:"
|
||||
echo "/etc/im-server/config config"
|
||||
echo "/opt/im-server binary files"
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
|
||||
<RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false"
|
||||
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>
|
||||
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
</Filters>
|
||||
<PatternLayout pattern="${pattern}" />
|
||||
<Policies>
|
||||
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
|
||||
<!-- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>-->
|
||||
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
|
||||
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
|
||||
<SizeBasedTriggeringPolicy size="100 MB"/>
|
||||
</Policies>
|
||||
|
||||
@@ -32,6 +32,7 @@ local_port 80
|
||||
## 是否使用内置DB。0使用mysql;1使用h2db。
|
||||
## MySQL需要把事物隔离级别改成"Read committed",使用命令来修改"set global transaction_isolation='read-committed';",其他数据库默认已经是这个级别不用修改
|
||||
## 如果使用MySQL,请在c3p0.xml文件中配置JDBC信息。
|
||||
## 如果是MySQL5.7,需要开启长索引的支持,在数据库中执行命令:"set global innodb_large_prefix=on;"。其他版本默认支持,不用修改。
|
||||
embed.db 1
|
||||
|
||||
## 是否自动清理历史消息记录,当为true时,IM服务会定时扫描t_messages_x和t_user_messages_x表,清除掉3年前的历史消息。
|
||||
@@ -56,6 +57,15 @@ token.key testim
|
||||
##token的过期时间,单位为毫秒,默认为无限期。如果需要设置无限期,客户端上一定需要加上token过期的处理。token过期的处理请参考文档的常见问题
|
||||
##token.expire_time 2592000000
|
||||
|
||||
##客户端(目前只有android)的应用签名(一个应用最取第一个签名),如果有多个签名(多个客户端),用英文逗号分开。获取签名方法请参考文档:https://docs.wildfirechat.cn/blogs/签名验证.html
|
||||
#connect.client_signature_list eNkezQ1g9OsnhfLSFUY1vzKDzhs=,xykezQ1g9OsnhfLSFUY1vzKDzhs=
|
||||
|
||||
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
|
||||
#connect.reject_empty_signature true
|
||||
|
||||
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
|
||||
#encrypt.use_aes256 true
|
||||
|
||||
##首次登录,是否接收之前的历史消息。
|
||||
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
|
||||
##1接收,会接收 message.max_queue 配置的条数的历史消息
|
||||
@@ -76,6 +86,9 @@ message.chatroom_remote_history_message 1
|
||||
##是否禁止陌生人聊天
|
||||
message.disable_stranger_chat false
|
||||
|
||||
##当禁止陌生人聊天时,允许聊天的用户id,比如管理员或者文件传输助手等。用户id以英文逗号分割。
|
||||
message.allow_stranger_chat_list admin,FireRobot,wfc_file_transfer
|
||||
|
||||
##黑名单策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃
|
||||
message.blacklist.strategy 0
|
||||
|
||||
@@ -139,6 +152,9 @@ friend.reject_request_duration 2592000000
|
||||
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
|
||||
friend.request_expiration_duration 604800000
|
||||
|
||||
##请求添加机器人为好友时,机器人是否自动接受,默认为true
|
||||
friend.robot_auto_accept true
|
||||
|
||||
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
|
||||
chatroom.participant_idle_time 900000
|
||||
|
||||
@@ -159,6 +175,10 @@ group.allow_robot_custom_operation_notification true
|
||||
## 如果应用需要退群或者踢人不通知普通成员,请设置此参数为3,然后修改客户端踢人或退群消息的flag为not_presist。
|
||||
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信息。当需要隐藏多个时以英文逗号分开;
|
||||
## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。
|
||||
## 注意,修改本配置不会对已经同步的信息产生影响。
|
||||
@@ -289,18 +309,25 @@ push.ios.server.address http://localhost:8085/ios/push
|
||||
|
||||
##消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.forward.url http://localhost:8087/im_event/message
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3
|
||||
#message.forward.url http://localhost:8888/im_event/message
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割,可以用-来指定区间,注意区间不能太大,因为要把区间内的所有数字都放入到Set中。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3,5-10
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割,可以用-来指定区间,注意区间不能太大,因为要把区间内的所有数字都放入到Set中。
|
||||
#message.forward.exclude_types 1,2,3,5-10
|
||||
|
||||
##敏感消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.sensitive.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。
|
||||
##此转发不受${message.forward.types}和${message.forward.exclude_types}限制。
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#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
|
||||
|
||||
@@ -12,6 +12,10 @@ if [ ! -d /etc/im-server ]; then
|
||||
mkdir /etc/im-server
|
||||
fi
|
||||
|
||||
if [ ! -d /var/log/im-server ]; then
|
||||
mkdir /var/log/im-server
|
||||
fi
|
||||
|
||||
mv -f /opt/im-server/config /etc/im-server
|
||||
systemctl daemon-reload
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -14,11 +14,11 @@ goto end
|
||||
:okHome
|
||||
|
||||
rem Set JavaHome if it exists
|
||||
if exist { "%JAVA_HOME%\bin\java" } (
|
||||
if exist [ "%JAVA_HOME%\bin\java" ] (
|
||||
set "JAVA="%JAVA_HOME%\bin\java""
|
||||
) else {
|
||||
) else (
|
||||
set "JAVA="java""
|
||||
}
|
||||
)
|
||||
|
||||
echo Using JAVA_HOME: "%JAVA_HOME%"
|
||||
echo Using WILDFIRECHAT_HOME: "%WILDFIRECHAT_HOME%"
|
||||
@@ -72,8 +72,13 @@ rem set JAVA_OPTS=%JAVA_OPTS% -XX:+UseGCLogFileRotation
|
||||
rem set JAVA_OPTS=%JAVA_OPTS% -XX:NumberOfGCLogFiles=10
|
||||
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 请设置JVM参数Xmx和Xms!!!
|
||||
echo "Please set Xmx and Xms parameters!"
|
||||
echo "Please set Xmx and Xms parameters!"
|
||||
echo "Please set Xmx and Xms parameters!"
|
||||
echo
|
||||
|
||||
rem set JAVA_OPTS=%JAVA_OPTS% -Xmx2G
|
||||
|
||||
@@ -18,7 +18,6 @@ while [ -h "$PRG" ]; do
|
||||
done
|
||||
|
||||
PRGDIR=`dirname "$PRG"`
|
||||
cd $PRGDIR
|
||||
cd ..
|
||||
WILDFIRECHAT_HOME=`pwd`
|
||||
|
||||
@@ -34,6 +33,8 @@ else
|
||||
fi
|
||||
export JAVA
|
||||
|
||||
$JAVA -version
|
||||
|
||||
WILDFIRECHAT_CONFIG_PATH=$WILDFIRECHAT_HOME
|
||||
|
||||
LOG_FILE=$WILDFIRECHAT_CONFIG_PATH/config/log4j2.xml
|
||||
@@ -85,6 +86,8 @@ JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=500"
|
||||
#JAVA_OPTS="$JAVA_OPTS -XX:NumberOfGCLogFiles=10"
|
||||
#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参数Xmx和Xms,设置为您为IM服务预留的内存大小,注意需要刨除操作系统占用,如果有其它系统也需要相应去除占用。"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
FROM openjdk:8-jre-alpine
|
||||
|
||||
ADD ../distribution/target/distribution-*-bundle-tar.tar.gz /opt/im-server/
|
||||
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 -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
|
||||
|
||||
VOLUME /opt/im-server/config
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
```
|
||||
mvn clean package
|
||||
```
|
||||
生成的软件包在```distribution/target/distribution-XX-bundle-tar.tar.gz```,把此软件包拷贝到docker目录下。
|
||||
|
||||
然后进入到docker目录下,编译镜像
|
||||
```
|
||||
sudo docker build -t im-server -f Dockerfile ..
|
||||
sudo docker build -t im-server .
|
||||
```
|
||||
|
||||
## 运行
|
||||
配置:
|
||||
运行需要手动指定配置目录,手动指定配置目录的方法如下,其中$PATH_TO_CONFIG为im配置目录,需要为绝对路径,模版为```distribution/src/main/resources```目录。另外需要创建h2数据库目录(如果用mysql就不需要了)、日志目录、内置存储服务目录(如果使用其它对象存储服务就不需要了)。
|
||||
```
|
||||
sudo docker run -it -v $PATH_TO_CONFIG:/opt/im-server/config -v $PATH_TO_LOGS:/opt/im-server/logs -v $PATH_TO_H2DB:/opt/im-server/h2db -v $PATH_TO_MEDIA:/opt/im-server/media -e JVM_XMX=256M -e JVM_XMS=256M -p 80:80 -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 18080:18080 im-server
|
||||
sudo docker run -it --name im-server -v $PATH_TO_CONFIG:/opt/im-server/config -v $PATH_TO_LOGS:/opt/im-server/logs -v $PATH_TO_H2DB:/opt/im-server/h2db -v $PATH_TO_MEDIA:/opt/im-server/media -e JVM_XMX=256M -e JVM_XMS=256M -p 80:80 -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 18080:18080 im-server
|
||||
```
|
||||
|
||||
## 导出镜像
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<version>0.97</version>
|
||||
<version>1.1.7</version>
|
||||
<name>Wildfire Chat</name>
|
||||
<description>Wildfire Chat Server</description>
|
||||
<inceptionYear>2019</inceptionYear>
|
||||
|
||||
@@ -12,12 +12,93 @@
|
||||
|
||||
# 更新记录
|
||||
|
||||
--------------
|
||||
Release note 1.1.7:
|
||||
1. 优化用户搜索功能。
|
||||
2. 推送消息中使用群备注。
|
||||
3. 推送消息中添加发送者和目标头像。
|
||||
4. 优化撤回消息流程。
|
||||
|
||||
--------------
|
||||
Release note 1.1.6:
|
||||
1. 支持用户设置查找自己的方法。
|
||||
2. 解决获取用户信息返回type无效的问题。
|
||||
3. 添加用户获取频道的功能。
|
||||
|
||||
--------------
|
||||
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:
|
||||
1. API获取用户信息时,过滤掉已经删除用户。
|
||||
2. 消息转发功能支持设置include/exclude功能,支持按区间过滤。
|
||||
3. 添加新的群组类型:组织群。组织群适用于公司部门群场景。
|
||||
4. 内置对象存储支持绝对路径和相对路径配置
|
||||
5. 当开启禁止陌生人聊天时,可以添加例外人员
|
||||
6. 解决user setting并发问题
|
||||
7. 添加可选的android平台签名验证功能。
|
||||
|
||||
--------------
|
||||
Release note 0.98:
|
||||
1. 解决linux多端登录错误问题
|
||||
2. 添加获取用户群组和共同群组功能
|
||||
3. 解决windows下脚本编码错误问题
|
||||
|
||||
--------------
|
||||
Release note 0.97:
|
||||
1. 升级部分依赖库到最新版本
|
||||
2. 添加名片消息默认推送信息
|
||||
3. 添加deb和rpm格式软件包
|
||||
4. 解决linux平台多端的问题
|
||||
|
||||
--------------
|
||||
Release note 0.96:
|
||||
|
After Width: | Height: | Size: 998 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 535 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 319 KiB |