Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a906bf352d | ||
|
|
37f1772705 | ||
|
|
0a05503c78 | ||
|
|
a702602758 | ||
|
|
c01e5b634d | ||
|
|
6c2848cbf7 | ||
|
|
ae3c8e0d25 | ||
|
|
2ef0059395 | ||
|
|
d91a2d9fd5 | ||
|
|
a4bcd5e29e | ||
|
|
fe4612c801 | ||
|
|
58ade23b23 | ||
|
|
f1e46fca75 | ||
|
|
1e17fa1db4 | ||
|
|
7094114ea3 | ||
|
|
c805bddca1 | ||
|
|
cb5754fe07 | ||
|
|
c014b78d95 | ||
|
|
8a13a32615 | ||
|
|
bc409042b0 | ||
|
|
49ad4f5eb6 | ||
|
|
8c93e2ee42 | ||
|
|
54286b4a55 | ||
|
|
594103e06b | ||
|
|
90e89978aa | ||
|
|
93b6e70804 | ||
|
|
b774e0d423 | ||
|
|
08b813cd9f | ||
|
|
24c6538084 | ||
|
|
724be0b273 | ||
|
|
63f0fc66ce | ||
|
|
327b8d43a8 | ||
|
|
df67b8e0c8 | ||
|
|
b4fcef1ced | ||
|
|
c43dfe26f4 | ||
|
|
aa1161131d | ||
|
|
a1188f5d52 | ||
|
|
6a10412940 | ||
|
|
8e3100e5b7 | ||
|
|
c17a5be171 | ||
|
|
7727fad4dc | ||
|
|
dd5b9b1847 | ||
|
|
92c3c98553 | ||
|
|
d13ed6f989 | ||
|
|
4e6188ee32 | ||
|
|
a183d30f89 | ||
|
|
3f4c2b0cea | ||
|
|
932ee9235f | ||
|
|
1e5ac9b787 | ||
|
|
ad5d4991c8 | ||
|
|
a2ee6c87eb | ||
|
|
30e01a7040 | ||
|
|
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 | ||
|
|
d4c6b1f616 | ||
|
|
ae3eb9c2df | ||
|
|
771a4d751f | ||
|
|
2bed06cf43 | ||
|
|
50f0330884 | ||
|
|
acd21faa9c | ||
|
|
6e570c74ae | ||
|
|
893b58cef4 | ||
|
|
bd2b037edb | ||
|
|
6acb1c968a | ||
|
|
6048748300 | ||
|
|
9be49c3d41 | ||
|
|
d9eccd39de | ||
|
|
ffaffc8fc1 | ||
|
|
5e1f4fe6c9 | ||
|
|
b5d884f9f6 | ||
|
|
c0840f3a73 | ||
|
|
34bd59f195 | ||
|
|
8e1d56b2ca | ||
|
|
a4eb64edd5 | ||
|
|
b141990661 | ||
|
|
0f9df0659f | ||
|
|
a2d4bf7d43 | ||
|
|
898c4f2419 | ||
|
|
e1a8a040df | ||
|
|
adb4f082f1 | ||
|
|
2724c79a79 | ||
|
|
ba01c90171 | ||
|
|
b8967ccaff | ||
|
|
0e6e23da13 | ||
|
|
88652af565 | ||
|
|
af58bf91a4 | ||
|
|
9d86539d01 | ||
|
|
2559fa7e48 | ||
|
|
20f71f5a21 | ||
|
|
326f76afd8 | ||
|
|
9f36d47ca8 | ||
|
|
57cdd57a30 |
@@ -11,10 +11,13 @@
|
||||
你认为正确的表现应该是什么样的。
|
||||
|
||||
#### 补充条件
|
||||
是否是毕现的,还是偶现的?是否只有在特殊的网络/设备/平台上出现,还是所有的都出现。还有您用的版本是什么时候的,是不是最新版
|
||||
是否是必现的,还是偶现的?是否只有在特殊的网络/设备/平台上出现,还是所有的都出现。还有您用的版本是什么时候的,是不是最新版
|
||||
|
||||
#### demo对比结果
|
||||
请用demo对比测试,demo上是什么状态。
|
||||
|
||||
#### 检索已有问题
|
||||
除了可以检索已有issue外,还可以去野火论坛查找已有问题,论坛地址为 https://bbs.wildfirechat.cn
|
||||
|
||||
#### star 我们
|
||||
给我们点个star,可以及时接收到我们回复信息,另外也是对我们支持人员辛苦工作的认可,激励我们更好更快地为大家服务。
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
## 功能特性
|
||||
* 极致地硬件利用率,IM服务最低128M内存即可运行,上不封顶。
|
||||
* 协议先进,采用MQTT+Protobuf组合,流量和性能极致优化。
|
||||
* 性能强大,专业版IM服务支持百万在线和集群部署。
|
||||
* 性能强大,专业版IM服务支持百万在线和集群部署,业内顶尖性能水平,详情参考野火性能报告。
|
||||
* 部署运维简单,依赖服务少,稍加配置一键启动。
|
||||
* 安全加密。网络连接AES加密。客户端数据库SqlCipher加密。安全无小事。
|
||||
* 全平台客户端,四端同时在线(移动端,pc端,web端和小程序端),数据和状态多端完美同步。
|
||||
* 全平台客户端,支持Android、iOS、Web、小程序、UniApp、Flutter、Windows、Mac OS、Linux等所有常见平台。
|
||||
* 四端同时在线(移动端,pc端,web端和小程序端),数据和状态多端完美同步。
|
||||
* 支持国产化。支持国产化操作系统、国产化芯片和国产操作系统。支持国密加密。
|
||||
* 客户端使用微信[mars](https://github.com/tencent/mars)连接库,野火IM可能是最适应中国网络国情的即时通讯服务。
|
||||
* 支持加速点加速,即可用于全球应用,也可用于政企内外双网复杂的网络环境。
|
||||
@@ -15,19 +16,23 @@
|
||||
* 音视频多种解决方案,丰俭由人,可自由选择。
|
||||
* 高级音视频功能强大,支持9人以上的群组视频通话,支持1080P视频,支持会议模式,支持百人以上会议,支持服务器端录制。
|
||||
* 全私有部署,可不依赖任何第三方服务,完全内网部署。
|
||||
* 功能齐全,涵盖所有常见即时通讯功能。另外具有强大的可扩展能力。Demo成熟完善,基本可以做到开箱即用,也可把SDK嵌入其它应用。
|
||||
* 功能齐全,涵盖所有常见即时通讯功能。另外具有强大的可扩展能力。代码开源率高,二次开发简单。
|
||||
* 结构设计合理,客户端分功能库、UI库和应用三层。应用成熟完善,开箱即用,也可把SDK嵌入其它应用。
|
||||
* 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。
|
||||
* API丰富,方便与其它服务系统的对接。
|
||||
* 拥有机器人和频道功能。
|
||||
* 代码开源率高,二次开发简单。可以先试用3到6个月,二开搞定后再购买。
|
||||
* 拥有机器人和公众号功能,免费的频道(公众号)管理后台。
|
||||
* 超级群组功能,可以支持万人大群。
|
||||
* 社区版IM服务和移动端免费商用,可以免费构建出完备的移动互联网应用。
|
||||
* 收费项目非常便宜,野火独有的试用模式,可以先部署到客户环境试用6个月,试用满意后再购买,避免上当受骗。
|
||||
* 技术支持专业和高效,核心研发人员及时处理issue和论坛回复。
|
||||
|
||||
## 野火开源项目
|
||||
主要包括以下项目:
|
||||
|
||||
| [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应用服务,模拟客户的应用服登陆处理逻辑及部分二次开发示例。 |
|
||||
| [app-server](https://github.com/wildfirechat/app-server) | [app-server](https://gitee.com/wfchat/app-server) | Demo应用服务,模拟客户的应用服登陆处理逻辑及部分二次开发示例。 |
|
||||
| [robot_server](https://github.com/wildfirechat/robot_server) | [robot_server](https://gitee.com/wfchat/robot_server) | 机器人服务,演示野火机器人对接其它系统的方法。 |
|
||||
| [push_server](https://github.com/wildfirechat/push_server) | [push_server](https://gitee.com/wfchat/push_server) | 推送服务器,可以对接所有的系统厂商推送服务或者第三方推送服务。 |
|
||||
| [wf-minio](https://github.com/wildfirechat/WF-minio) | [wf-minio](https://gitee.com/wfchat/WF-minio) | 私有对象存储服务,用来支持野火IM专业版的文件存储。 |
|
||||
@@ -35,19 +40,26 @@
|
||||
| [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/)。 |
|
||||
|
||||
## 野火开发文档
|
||||
[在线文档](https://docs.wildfirechat.cn/)
|
||||
|
||||
## 野火IM论坛
|
||||
[野火IM论坛](https://bbs.wildfirechat.cn)
|
||||
|
||||
## 野火性能测试报告及测试方法
|
||||
[Github](https://github.com/wildfirechat/Performance_Test), [码云](https://gitee.com/wfchat/Performance_Test)。
|
||||
|
||||
## 野火Demo
|
||||
请使用微信扫码下载安装体验野火IM移动客户端
|
||||
|
||||
@@ -61,74 +73,174 @@ PC客户端点[这里](https://github.com/wildfirechat/vue-pc-chat/releases)下
|
||||
|
||||

|
||||
|
||||
## 快速使用
|
||||
野火提供免费的社区版IM服务和移动端,包括完整的移动端即时通讯和实时音视频功能,可以无条件商用。您可以直接从开源项目里下载到完整的后端和移动端产品,包括社区版IM服务、应用服务、开放平台服务、频道(公众号)服务、机器人服务、推送服务以及Android和iOS端源码。可以按照[快速开始](https://docs.wildfirechat.cn/quick_start/)来部署应用服务和IM服务,然后打包移动端,以最小化运行。之后可以详细阅读文档部署其他支撑服务。
|
||||
## 快速开始
|
||||
可以按照[快速开始](https://docs.wildfirechat.cn/quick_start/)来部署应用服务和IM服务,然后打包移动端,就可以完成聊天和通话功能。
|
||||
|
||||
## 应用截图
|
||||

|
||||
之后再部署开放平台服务、频道(公众号)服务、机器人服务、推送服务、Turn服务(音视频服务)来实现完整的应用功能,详情可以详细阅读文档。
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-message-view.png" width = 50% height = 50% />
|
||||
## 联系我们
|
||||
商务合作请微信联系:
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-contact-view.png" width = 50% height = 50% />
|
||||
* 微信1:wildfirechat
|
||||
* 微信2:wfchat
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-discover-view.png" width = 50% height = 50% />
|
||||
## 问题交流
|
||||
|
||||
<img src="http://static.wildfirechat.cn/ios-settings-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-messagelist-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-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的修改和新需求的开发我们也会尽快解决。
|
||||
|
||||
|
||||
## 编译
|
||||
在安装JDK1.8以上及maven的前提下,在命令行中执行```mvn clean package```,生成的目标文件在```./distribution/target/distribution-xxxx-bundle-tar.tar.gz```
|
||||
> 由于使用了一个git的maven插件,如果本地没有git信息就会编译出错,请使用```git clone```的方法下载代码,或者下载压缩包解压后在根目录创建```.git```的空目录。建议用```git clone```的方式下载代码。
|
||||
```
|
||||
mvn clean package
|
||||
```
|
||||
生成的目标文件在```./distribution/target/distribution-xxxx-bundle-tar.tar.gz```
|
||||
|
||||
## 配置
|
||||
解压```distribution-xxxx-bundle-tar.tar.gz```,修改解压出来的```config```目录下的```wildfirechat.conf```。修改如下部分:
|
||||
1. 修改```server.ip```为您的服务器的公网IP,或者域名。如果用域名需要做好域名解析。
|
||||
2. 可以阅读配置文件注释和文档,对其它配置项进行调整。
|
||||
解压```distribution-xxxx-bundle-tar.tar.gz```,修改解压出来的```config```目录下的```wildfirechat.conf```,可以阅读配置文件注释和文档,对其它配置项进行调整。
|
||||
|
||||
## 运行
|
||||
在程序目录运行如下命令:
|
||||
在解压```distribution-xxxx-bundle-tar.tar.gz```后的目录下运行如下命令:
|
||||
```
|
||||
./bin/wildfirechat.sh
|
||||
```
|
||||
|
||||
## 验证
|
||||
1. 在浏览器中输入地址 ```http://${ip}/api/version```可以看到返回一个json文件。
|
||||
2. 部署[应用服务](应用服务),配置和编译[Android客户端](https://github.com/wildfirechat/android-chat)和[iOS客户端](https://github.com/wildfirechat/ios-chat)进行验证。详情可参考[快速开始](https://docs.wildfirechat.cn/quick_start/)。
|
||||
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.46和0.47版本升级到0.48及以后版本时,可能会提示flyway migrate 38错误,请执行 [修复脚本](https://github.com/wildfirechat/server/blob/wildfirechat/flyway_repaire_migrate_38.sql) 进行修复。0.46和0.47版本之外的版本不会出现此问题。
|
||||
3. 从0.54之前版本升级到0.54及以后版本时,会提示flyway migrate错误。因为0.54版本删除了sql脚本中默认敏感词的内容,flyway checksum失败。请执行```update flyway_schema_history set checksum = 0 where script = 'V17__add_default_sensitive_word.sql';```来修复。
|
||||
4. 从0.59之前的版本升级到之后的版本执行数据库升级时间比较长,请耐心等待提示运行成功,避免中途中断。
|
||||
2. 0.50版本添加了是否允许客户端发送群操作通知的配置。如果您在客户端自定义群通知,需要在服务器端配置允许,没有使用自定义群操作通知的不受影响。***
|
||||
3. 0.46和0.47版本升级到0.48及以后版本时,可能会提示flyway migrate 38错误,请执行 [修复脚本](https://github.com/wildfirechat/server/blob/wildfirechat/flyway_repaire_migrate_38.sql) 进行修复。0.46和0.47版本之外的版本不会出现此问题。
|
||||
4. 从0.54之前版本升级到0.54及以后版本时,会提示flyway migrate错误。因为0.54版本删除了sql脚本中默认敏感词的内容,flyway checksum失败。请执行```update flyway_schema_history set checksum = 0 where script = 'V17__add_default_sensitive_word.sql';```来修复。
|
||||
5. 从0.59之前的版本升级到之后的版本执行数据库升级时间比较长,请耐心等待提示运行成功,避免中途中断。
|
||||
6. 0.62/0.63 版本有严重的问题,请使用0.64及以后版本,或者0.61版。
|
||||
7. 从0.68 版本起添加了pc在线是否默认手机接收推送的开关,默认为开,与以前版本作用相反,请注意兼容(可以关掉与之前保持一致或者升级客户端)
|
||||
8. 从0.78 版本起把MySQL数据库中关键字都改为大小写敏感,另外生成id的方法也做了改变,只生成小写的id,避免出现id重复的问题,建议所有客户都升级
|
||||
9. 从0.79 版本起把log4j升级到log4j2,因为log4j已经不再维护而且还有已知的漏洞,建议所有客户都升级,升级时注意更新log4j2的配置文件
|
||||
10. 0.97版本更改了启动脚本```wildfirechat.sh```,如果是升级服务,请注意更新启动脚本。
|
||||
|
||||
## 维护说明
|
||||
野火设计理念当中,IM服务和客户端协议栈构成个管道工具,数据在人和人或者人和服务或者服务和服务之间传递,可以通过Server API和自定义消息来对接和开发业务。业务系统把IM系统当作一个工具来使用,是不需要把任何业务逻辑写在IM服务中的。
|
||||
|
||||
## 联系我们
|
||||
如果修改了IM服务可能会引起跟客户端协议栈的不兼容,以后也没有可能从社区版IM服务迁移到专业版IM服务,还有一旦修改就跟我们代码不一样了,如果出了问题我们就无法分析和解决。所以 ***我们强烈不推荐在IM服务修改代码,如果修改过就不再提供任何技术支持和服务了***。除了IM服务以外的所有代码可以任意修改。
|
||||
|
||||
商务合作请使用如下邮箱和微信联系:
|
||||
现有接口足够对接和二开任何业务了,如果发现无法实现你们的业务需求,可以在[论坛](https://bbs.wildfirechat.cn)来咨询,我们会分析如何实现,如果需要添加新接口,我们会及时免费添加。请切记:***不要修改IM服务的代码!*** ***不要修改IM服务的代码!*** ***不要修改IM服务的代码!***
|
||||
|
||||
邮箱: support@wildfirechat.cn 微信1:wfchat 微信2:wildfirechat
|
||||
详细维护说明请参考 [野火维护说明](https://docs.wildfirechat.cn/base_knowledge/maintain.html)。
|
||||
|
||||
## 问题交流
|
||||
## 服务对象
|
||||
因为野火的使用范围比较广,难免被一些不法分子利用,国内反诈反赌力度很大,所以国内多地警方都跟我们都有过联系。***为了预防我们的产品被用于非法目的,试用及购买只能支持境内法人单位,不接受个人或者境外团体。如果我们发现产品被用于非法目的,我们会立即停止技术支持服务并且报警和配合警方调查。请用于非法目的用户绕行!***
|
||||
|
||||
1. 如果大家发现bug,请在GitHub提issue;如果有需求也请给我们提issue。
|
||||
2. 其他问题,请到[野火IM论坛](http://bbs.wildfirechat.cn/)进行交流学习
|
||||
3. 关注我们的公众号。我们有新版本发布或者有重大更新会通过公众号通知大家,另外我们也会不定期的发布一些关于野火IM的技术介绍。
|
||||
## 应用截图
|
||||
登录界面
|
||||
|
||||
<img src="http://static.wildfirechat.cn/wx_wfc_qrcode.jpg" width = 50% height = 50% />
|
||||
<img src="./screenshots/1_login.png" width = 50% height = 50% />
|
||||
|
||||
> 我们有研发工程师轮流值班处理issue和论坛,一般简单问题几个小时就会回复一遍,疑难Bug的修改和新需求的开发我们也会尽快解决。
|
||||
会话列表
|
||||
|
||||
<img src="./screenshots/2_conversation_list.png" width = 50% height = 50% />
|
||||
|
||||
好友列表
|
||||
|
||||
<img src="./screenshots/3_contacts_list.png" width = 50% height = 50% />
|
||||
|
||||
工作台
|
||||
|
||||
<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相关业务。
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#native2ascii -encoding UTF-8 messages.properties temp_messages.properties
|
||||
Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
|
||||
Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
|
||||
@@ -1,2 +0,0 @@
|
||||
Above_Greeting_Message=This's the greeting
|
||||
Friend_Can_Start_Chat=You're already friend, start chat now.
|
||||
@@ -1,2 +0,0 @@
|
||||
Above_Greeting_Message=This's the greeting
|
||||
Friend_Can_Start_Chat=You're already friend, start chat now.
|
||||
@@ -1,2 +0,0 @@
|
||||
Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
|
||||
Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
|
||||
@@ -1,2 +0,0 @@
|
||||
Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
|
||||
Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
|
||||
@@ -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
|
||||
@@ -42,6 +42,9 @@ embed.db 1
|
||||
## 使用mongodb时次开关无效(因为mongodb设置了消息过期时间,会自动清理,仅专业版支持mongodb)。
|
||||
db.auto_clean_history_messages true
|
||||
|
||||
## h2db数据库的路径,默认为程序目录下的,可以指定其他目录。如果使用MySQL,可以忽略此配置
|
||||
h2db.path ./h2db/wfchat
|
||||
|
||||
##服务器管理接口密钥。如果修改此端口需要同步修改使用管理API的地方,比如应用服务。
|
||||
http.admin.secret_key 123456
|
||||
|
||||
@@ -56,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 配置的条数的历史消息
|
||||
@@ -76,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
|
||||
|
||||
@@ -108,6 +123,12 @@ message.group_mute_exception_types 401,402,403,404,405,407,408,410,411
|
||||
## 用户被全局禁言时允许发送的消息类型
|
||||
message.global_mute_exception_types 401,402,403,404,405,407,408,410,411
|
||||
|
||||
## 离线用户推送过期天数,0是永不过期,建议配置为7天。
|
||||
message.push_expired_days 7
|
||||
|
||||
## 群发消息(包括server api群发和全局频道群发)时,目标用户是否来自于t_user表。如果使用野火托管用户信息,请设置为true,否则设置为false。
|
||||
message.broadcast.target_from_user_table true
|
||||
|
||||
## 消息转发功能开启时,开关是否不转发server api接口消息。
|
||||
## 当为true时,不转发server api发送的消息;当为false时,转发server api发送的消息。
|
||||
message.no_forward_admin_message false
|
||||
@@ -127,6 +148,9 @@ friend.disable_search false
|
||||
##禁止按照昵称搜索用户。
|
||||
friend.disable_nick_name_search false
|
||||
|
||||
##禁止按照用户id搜索用户,默认为true。
|
||||
friend.disable_user_id_search true
|
||||
|
||||
##禁止发送好友邀请,通过server api添加好友不受此限制(force参数需要为true)
|
||||
friend.disable_friend_request false
|
||||
|
||||
@@ -139,11 +163,8 @@ friend.reject_request_duration 2592000000
|
||||
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
|
||||
friend.request_expiration_duration 604800000
|
||||
|
||||
##添加好友后会发送欢迎消息,比如"你们已经是好友了,可以聊天了"。这个开关控制是用旧的方式还是用新的方式。
|
||||
##旧的方式会发送notification消息(contenttype是80),内容会根据好友接收者的语言选择对应的语言,如果双方语言不一致会导致另外一方看到的不是本地语言。
|
||||
##新的方式会发送添加好友消息(contenttype是93)和欢迎消息(contenttype是92),需要客户端实现这两种消息。
|
||||
##如果客户端已经实现这两种消息可以打开这个开关(客户端2020.6.30添加了此消息类型)。
|
||||
friend.new_welcome_message true
|
||||
##请求添加机器人为好友时,机器人是否自动接受,默认为true
|
||||
friend.robot_auto_accept true
|
||||
|
||||
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
|
||||
chatroom.participant_idle_time 900000
|
||||
@@ -154,6 +175,18 @@ chatroom.rejoin_when_active true
|
||||
## 当一个聊天室不存在时,如果有用户加入就自动创建
|
||||
chatroom.create_when_not_exist true
|
||||
|
||||
## 一个用户同一时刻只能加入一个聊天室。
|
||||
## 当一个客户端加入一个聊天室时,如果这个客户端已经加入另外一个聊天室了,会自动退出之前的聊天室。
|
||||
## 当一个客户端加入一个聊天室时,如果这个用户的其他端已经加入一个聊天室了,kickoff_other_platform为true时会自动退出之前的聊天室,为false时会返回225的错误码。
|
||||
## 当自动退出聊天室时,客户端不会收到任何通知,只是不会再收到消息。
|
||||
chatroom.kickoff_other_platform true
|
||||
|
||||
## 是否允许群主不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为true。
|
||||
group.allow_owner_recall_self_msg true
|
||||
|
||||
## 是否允许群管理员不受限制地撤回自己发送的消息。false可以${message.recall_time_limit}撤回自己的消息;true可以撤回任意时间自己的消息。默认为false。
|
||||
group.allow_manager_recall_self_msg false
|
||||
|
||||
## 是否允许客户端发送操作群的自定义群通知消息
|
||||
group.allow_client_custom_operation_notification true
|
||||
|
||||
@@ -164,6 +197,13 @@ 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
|
||||
|
||||
## 是否禁止陌生人拉人入群,默认为false
|
||||
group.disable_stranger_invite false
|
||||
|
||||
## 隐藏用户信息属性类型,2是性别,3是电话号码,4是邮箱,5是地址,6是公司信息,7是社交账号,8是Extra信息。当需要隐藏多个时以英文逗号分开;
|
||||
## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。
|
||||
## 注意,修改本配置不会对已经同步的信息产生影响。
|
||||
@@ -176,6 +216,9 @@ user.keep_display_name_when_destroy true
|
||||
# 因此需要分段多次同步,此开关定义了每次同步的数据的条数。此需要客户端支持,客户端SDK在2021.5.25日后支持此功能。如果确认所有客户端都在这个日志之后才可以打开此设置。
|
||||
#sync.data_part_size 1000
|
||||
|
||||
## 是否关闭api/version接口。api/version方法可以用来检查IM服务版本,上线确认无问题后,可以关掉这个接口。
|
||||
#http.close_api_version false
|
||||
|
||||
#*********************************************************************
|
||||
# 限频配置
|
||||
#*********************************************************************
|
||||
@@ -190,11 +233,6 @@ http.channel.rate_limit 1000
|
||||
##客户端请求频率限制,默认是5秒100次。通常情况下不要修改这个值。
|
||||
client.request_rate_limit 100
|
||||
|
||||
#*********************************************************************
|
||||
# hazelcase configuration
|
||||
#*********************************************************************
|
||||
hazelcast.configuration config/hazelcast.xml
|
||||
|
||||
#*********************************************************************
|
||||
# Media server configuration
|
||||
#*********************************************************************
|
||||
@@ -253,7 +291,10 @@ server.multi_endpoint false
|
||||
## 是否支持PC多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开PC端多端登录。
|
||||
server.multi_pc_endpoint false
|
||||
|
||||
# 多平台连接状态通知(仅当multi_endpoint为false时有效),true时移动端可以收到pc或web端登录的通知。
|
||||
## 是否支持PAD多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开PAD端多端登录。
|
||||
server.multi_pad_endpoint false
|
||||
|
||||
# 多平台连接状态通知(仅当multi_endpoint为false时有效),true时移动端可以收到pc或pad或web端登录的通知。
|
||||
server.multi_platform_notification true
|
||||
|
||||
# 当pc或者web在线时,手机是否默认静音,默认为true。注意仅影响默认值,用户可以手动切换是否静音。
|
||||
@@ -301,17 +342,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
|
||||
|
||||
##设备信息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
@@ -340,10 +387,12 @@ push.ios.server.address http://localhost:8085/ios/push
|
||||
#*********************************************************************
|
||||
# Sensitive configuration
|
||||
#*********************************************************************
|
||||
## 内置文本敏感词过滤处理方法,0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***;3 记录并继续发送
|
||||
## 内置文本敏感词过滤处理方法,当命中敏感词后,消息会被记录到t_sensitive_messages表中,然后根据type类型做不同的处理,处理方式如下:
|
||||
## 0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***然后正常发送;3 正常发送。
|
||||
## 如果开启 message.sensitive.forward.url 配置,命中敏感词的消息还会被回调到这个地址
|
||||
sensitive.filter.type 0
|
||||
|
||||
## 如果内置敏感词库无法满足您的需求,可以自己开发部署敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址
|
||||
## 如果内置敏感词库无法满足您的需求,可以开发部署独立敏感词审核服务。配置如下地址和消息类型,IM服务会把指定消息类型的消息回调到指定地址,内置的敏感词审核和敏感词转发功能就不再起作用了。
|
||||
## 审核服务返回状态码200表示继续发送,如果需要替换内容,返回状态码200并且内容为替换后的内容。返回403表示不允许发送。其它错误继续发送。
|
||||
## 独立审核服务地址,IM服务会post SendMessageData。如果需要修改消息内容,返回 MessagePayload。请参考应用服务中 "/message/censor" Mapping.
|
||||
#sensitive.remote_server_url http://192.168.3.202:8888/message/censor
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
alter table `t_group_member` add INDEX `group_member_mid_index` (`_mid`);
|
||||
+19
@@ -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)
|
||||
);
|
||||
@@ -10,7 +10,7 @@ CREATE TABLE `t_messages_0` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -28,7 +28,7 @@ CREATE TABLE `t_messages_1` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -46,7 +46,7 @@ CREATE TABLE `t_messages_2` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -63,7 +63,7 @@ CREATE TABLE `t_messages_3` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -81,7 +81,7 @@ CREATE TABLE `t_messages_4` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -99,7 +99,7 @@ CREATE TABLE `t_messages_5` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -116,7 +116,7 @@ CREATE TABLE `t_messages_6` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -134,7 +134,7 @@ CREATE TABLE `t_messages_7` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -152,7 +152,7 @@ CREATE TABLE `t_messages_8` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -169,7 +169,7 @@ CREATE TABLE `t_messages_9` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -187,7 +187,7 @@ CREATE TABLE `t_messages_10` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -205,7 +205,7 @@ CREATE TABLE `t_messages_11` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -222,7 +222,7 @@ CREATE TABLE `t_messages_12` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -240,7 +240,7 @@ CREATE TABLE `t_messages_13` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -258,7 +258,7 @@ CREATE TABLE `t_messages_14` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -275,7 +275,7 @@ CREATE TABLE `t_messages_15` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -293,7 +293,7 @@ CREATE TABLE `t_messages_16` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -311,7 +311,7 @@ CREATE TABLE `t_messages_17` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -328,7 +328,7 @@ CREATE TABLE `t_messages_18` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -346,7 +346,7 @@ CREATE TABLE `t_messages_19` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -364,7 +364,7 @@ CREATE TABLE `t_messages_20` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -381,7 +381,7 @@ CREATE TABLE `t_messages_21` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -399,7 +399,7 @@ CREATE TABLE `t_messages_22` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -417,7 +417,7 @@ CREATE TABLE `t_messages_23` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -434,7 +434,7 @@ CREATE TABLE `t_messages_24` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -452,7 +452,7 @@ CREATE TABLE `t_messages_25` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -470,7 +470,7 @@ CREATE TABLE `t_messages_26` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -487,7 +487,7 @@ CREATE TABLE `t_messages_27` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -505,7 +505,7 @@ CREATE TABLE `t_messages_28` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -523,7 +523,7 @@ CREATE TABLE `t_messages_29` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -540,7 +540,7 @@ CREATE TABLE `t_messages_30` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -558,7 +558,7 @@ CREATE TABLE `t_messages_31` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -576,7 +576,7 @@ CREATE TABLE `t_messages_32` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -593,7 +593,7 @@ CREATE TABLE `t_messages_33` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -611,7 +611,7 @@ CREATE TABLE `t_messages_34` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
@@ -629,7 +629,7 @@ CREATE TABLE `t_messages_35` (
|
||||
`_data` BLOB NOT NULL,
|
||||
`_searchable_key` TEXT DEFAULT NULL,
|
||||
`_dt` DATETIME NOT NULL,
|
||||
INDEX `message_uid_index` (`_mid` DESC)
|
||||
UNIQUE INDEX `message_uid_index` (`_mid` DESC)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8mb4
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
alter table `t_group_member` add INDEX `group_member_mid_index` (`_mid`);
|
||||
+2722
File diff suppressed because it is too large
Load Diff
+24
-55
@@ -1,11 +1,11 @@
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<relativePath>../</relativePath>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.95</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>moquette-broker</artifactId>
|
||||
@@ -37,14 +37,14 @@
|
||||
<!--用于与slf4j保持桥接-->
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>2.17.2</version>
|
||||
<artifactId>log4j-slf4j2-impl</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</dependency>
|
||||
<!-- slf4j核心包-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<version>2.0.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lmax</groupId>
|
||||
@@ -65,6 +65,18 @@
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>3.25.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
@@ -120,7 +132,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.10</version>
|
||||
<version>1.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -129,37 +141,18 @@
|
||||
<version>3.11.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.xiaoleilu/hutool -->
|
||||
<dependency>
|
||||
<groupId>com.xiaoleilu</groupId>
|
||||
<artifactId>hutool</artifactId>
|
||||
<version>2.15.11</version>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.26</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.5.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- needs extra dependencies: objenesis & hamcrest -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.fusesource.mqtt-client</groupId>
|
||||
<artifactId>mqtt-client</artifactId>
|
||||
@@ -169,29 +162,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-client</artifactId>
|
||||
<version>9.2.0.M1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<!-- use 2.6.0 for Java 7 projects -->
|
||||
<version>2.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.191</version>
|
||||
<scope>test</scope>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -214,14 +185,12 @@
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.13.1</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</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;
|
||||
|
||||
@@ -95,9 +95,15 @@ public class PushServer {
|
||||
pushMessage.deviceToken = session.getDeviceToken();
|
||||
pushMessage.unReceivedMsg = badge;
|
||||
pushMessage.userId = session.getUsername();
|
||||
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS || session.getPlatform() == ProtoConstants.Platform.Platform_Android) {
|
||||
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS ||
|
||||
session.getPlatform() == ProtoConstants.Platform.Platform_iPad ||
|
||||
session.getPlatform() == ProtoConstants.Platform.Platform_Android ||
|
||||
session.getPlatform() == ProtoConstants.Platform.Platform_APad ||
|
||||
session.getPlatform() == ProtoConstants.Platform.Platform_Harmony ||
|
||||
session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad
|
||||
) {
|
||||
String url = androidPushServerUrl;
|
||||
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS) {
|
||||
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS || session.getPlatform() == ProtoConstants.Platform.Platform_iPad) {
|
||||
url = iOSPushServerUrl;
|
||||
pushMessage.voipDeviceToken = session.getVoipDeviceToken();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.xiaoleilu.loServer;
|
||||
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.DateUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.action.ClassUtil;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.xiaoleilu.loServer;
|
||||
|
||||
import com.xiaoleilu.hutool.util.DateUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.AdminActionHandler;
|
||||
|
||||
@@ -5,11 +5,9 @@ import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.xiaoleilu.hutool.lang.Singleton;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.FileUtil;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Singleton;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.action.DefaultIndexAction;
|
||||
import com.xiaoleilu.loServer.action.UnknownErrorAction;
|
||||
@@ -189,7 +187,7 @@ public class ServerSetting {
|
||||
* @param filterClass Filter类
|
||||
*/
|
||||
public static void setFilter(String path, Class<? extends Filter> filterClass) {
|
||||
setFilter(path, (Filter)Singleton.get(filterClass));
|
||||
setFilter(path, (Filter) Singleton.get(filterClass));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------- Filter end
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ abstract public class Action {
|
||||
protected static RateLimiter robotLimiter = null;
|
||||
protected static RateLimiter channelLimiter = null;
|
||||
|
||||
protected static boolean closeApiVersion = false;
|
||||
|
||||
public static void init(IConfig config) {
|
||||
int adminRate = 10000;
|
||||
int robotRate = 1000;
|
||||
@@ -70,6 +72,11 @@ abstract public class Action {
|
||||
adminLimiter = new RateLimiter(10, adminRate);
|
||||
robotLimiter = new RateLimiter(10, robotRate);
|
||||
channelLimiter = new RateLimiter(10, channelRate);
|
||||
|
||||
try {
|
||||
closeApiVersion = Boolean.parseBoolean(config.getProperty(HTTP_CLOSE_API_VERSION, "false"));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected class Result {
|
||||
|
||||
@@ -31,6 +31,11 @@ public class CheckTokenAction extends Action {
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
if(closeApiVersion) {
|
||||
response.sendError(HttpResponseStatus.NOT_FOUND, "404 Not found!");
|
||||
return true;
|
||||
}
|
||||
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
String userId = request.getParam("userId");
|
||||
String clientId = request.getParam("clientId");
|
||||
|
||||
@@ -8,13 +8,11 @@ import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.DateUtil;
|
||||
import com.xiaoleilu.hutool.util.FileUtil;
|
||||
import com.xiaoleilu.hutool.util.ReUtil;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import com.xiaoleilu.loServer.ServerSetting;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
@@ -24,6 +22,8 @@ import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static cn.hutool.core.date.DatePattern.HTTP_DATETIME_PATTERN;
|
||||
|
||||
/**
|
||||
* 默认的主页Action,当访问主页且没有定义主页Action时,调用此Action
|
||||
*
|
||||
@@ -90,11 +90,13 @@ public class FileAction extends Action {
|
||||
}
|
||||
|
||||
response.setContent(file);
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");
|
||||
private static final SimpleDateFormat HTTP_DATE_FORMATER = new SimpleDateFormat(DateUtil.HTTP_DATETIME_PATTERN, Locale.US);
|
||||
private static final SimpleDateFormat HTTP_DATE_FORMATER = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.xiaoleilu.loServer.action;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.moquette.spi.IMessagesStore;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -30,8 +30,12 @@ public class VersionAction extends Action {
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
if(closeApiVersion) {
|
||||
response.sendError(HttpResponseStatus.NOT_FOUND, "404 Not found!");
|
||||
return true;
|
||||
}
|
||||
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
try {
|
||||
|
||||
response.setContent(Utility.formatJson(gson.toJson(GitRepositoryState.getGitRepositoryState())));
|
||||
|
||||
@@ -48,10 +48,6 @@ public class CreateChatroomAction extends AdminAction {
|
||||
inputCreateChatroom.setChatroomId(messagesStore.getShortUUID());
|
||||
}
|
||||
|
||||
if (inputCreateChatroom.getPortrait() == null || inputCreateChatroom.getPortrait().length() == 0) {
|
||||
inputCreateChatroom.setPortrait("https://avatars.io/gravatar/" + inputCreateChatroom.getChatroomId());
|
||||
}
|
||||
|
||||
WFCMessage.ChatroomInfo info = inputCreateChatroom.toChatroomInfo();
|
||||
messagesStore.createChatroom(inputCreateChatroom.getChatroomId(), info);
|
||||
setResponseContent(RestResult.ok(new OutputCreateChatroom(inputCreateChatroom.getChatroomId())), response);
|
||||
|
||||
@@ -45,23 +45,13 @@ public class CreateRobotAction extends AdminAction {
|
||||
if (inputCreateRobot != null
|
||||
&& !StringUtil.isNullOrEmpty(inputCreateRobot.getName())) {
|
||||
|
||||
if(StringUtil.isNullOrEmpty(inputCreateRobot.getPassword())) {
|
||||
inputCreateRobot.setPassword(UUIDGenerator.getUUID());
|
||||
}
|
||||
|
||||
if(StringUtil.isNullOrEmpty(inputCreateRobot.getUserId())) {
|
||||
inputCreateRobot.setUserId(messagesStore.getShortUUID());
|
||||
}
|
||||
|
||||
if (inputCreateRobot.getPortrait() == null || inputCreateRobot.getPortrait().length() == 0) {
|
||||
inputCreateRobot.setPortrait("https://avatars.io/gravatar/" + inputCreateRobot.getUserId());
|
||||
}
|
||||
|
||||
WFCMessage.User newUser = inputCreateRobot.toUser();
|
||||
|
||||
|
||||
try {
|
||||
messagesStore.addUserInfo(newUser, inputCreateRobot.getPassword());
|
||||
messagesStore.addUserInfo(newUser);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, IMExceptionEvent.EventType.ADMIN_API_Exception);
|
||||
|
||||
@@ -47,10 +47,6 @@ public class CreateUserAction extends AdminAction {
|
||||
&& !StringUtil.isNullOrEmpty(inputCreateUser.getName())
|
||||
&& (inputCreateUser.getType() == ProtoConstants.UserType.UserType_Normal || inputCreateUser.getType() == ProtoConstants.UserType.UserType_Admin || inputCreateUser.getType() == ProtoConstants.UserType.UserType_Super_Admin)) {
|
||||
|
||||
if(StringUtil.isNullOrEmpty(inputCreateUser.getPassword())) {
|
||||
inputCreateUser.setPassword(UUIDGenerator.getUUID());
|
||||
}
|
||||
|
||||
if(StringUtil.isNullOrEmpty(inputCreateUser.getUserId())) {
|
||||
inputCreateUser.setUserId(messagesStore.getShortUUID());
|
||||
}
|
||||
@@ -85,7 +81,7 @@ public class CreateUserAction extends AdminAction {
|
||||
|
||||
|
||||
try {
|
||||
messagesStore.addUserInfo(newUserBuilder.build(), inputCreateUser.getPassword());
|
||||
messagesStore.addUserInfo(newUserBuilder.build());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, IMExceptionEvent.EventType.ADMIN_API_Exception);
|
||||
|
||||
+59
@@ -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;
|
||||
}
|
||||
}
|
||||
+55
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,9 @@ public class GetGroupInfoAction extends AdminAction {
|
||||
pojoGroupInfo.setJoin_type(groupInfo.getJoinType());
|
||||
pojoGroupInfo.setPrivate_chat(groupInfo.getPrivateChat());
|
||||
pojoGroupInfo.setSearchable(groupInfo.getSearchable());
|
||||
pojoGroupInfo.setMax_member_count(groupInfo.getMemberCount());
|
||||
pojoGroupInfo.setHistory_message(groupInfo.getHistoryMessage());
|
||||
pojoGroupInfo.setSuper_group(groupInfo.getSuperGroup()>0);
|
||||
result = RestResult.ok(pojoGroupInfo);
|
||||
}
|
||||
setResponseContent(result, response);
|
||||
|
||||
+69
@@ -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;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.annotation.HttpMethod;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Route(APIPath.User_Online_List)
|
||||
@HttpMethod("POST")
|
||||
public class GetOnlineUserAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
GetOnlineUserRequest getOnlineUserRequest = getRequestBody(request.getNettyRequest(), GetOnlineUserRequest.class);
|
||||
if (getOnlineUserRequest.nodeId == 1) {
|
||||
GetOnlineUserResult result = messagesStore.getOnlineUsers(getOnlineUserRequest.offset, getOnlineUserRequest.count);
|
||||
setResponseContent(RestResult.ok(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));
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.InputGetChatroomInfo;
|
||||
import cn.wildfirechat.pojos.InputUserId;
|
||||
import cn.wildfirechat.pojos.OutputStringList;
|
||||
import cn.wildfirechat.pojos.OutputUserChatroom;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.annotation.HttpMethod;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.moquette.persistence.UserClientEntry;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Route(APIPath.Chatroom_GetUserChatroom)
|
||||
@HttpMethod("POST")
|
||||
public class GetUserChatroomAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
InputUserId inputUserId = getRequestBody(request.getNettyRequest(), InputUserId.class);
|
||||
String userId = inputUserId.getUserId();
|
||||
if (!StringUtil.isNullOrEmpty(userId)) {
|
||||
OutputUserChatroom outputUserChatroom = messagesStore.getUserChatroom(userId);
|
||||
|
||||
RestResult result;
|
||||
if (outputUserChatroom != null) {
|
||||
result = RestResult.ok(outputUserChatroom);
|
||||
} else {
|
||||
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
|
||||
}
|
||||
setResponseContent(result, response);
|
||||
} else {
|
||||
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+55
@@ -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.InputGetUserGroupByType;
|
||||
import cn.wildfirechat.pojos.InputUserId;
|
||||
import cn.wildfirechat.pojos.OutputGroupIds;
|
||||
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_User_Groups_By_Type)
|
||||
@HttpMethod("POST")
|
||||
public class GetUserGroupsByTypeAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
InputGetUserGroupByType input = getRequestBody(request.getNettyRequest(), InputGetUserGroupByType.class);
|
||||
if (input != null
|
||||
&& (!StringUtil.isNullOrEmpty(input.getUserId()))) {
|
||||
|
||||
Set<String> groupIds = messagesStore.getUserGroupIds(input.getUserId(), input.getGroupMemberTypes());
|
||||
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;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.GetOnlineUserCountResult;
|
||||
import cn.wildfirechat.pojos.GetUserSessionResult;
|
||||
import cn.wildfirechat.pojos.InputUserId;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.annotation.HttpMethod;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Route(APIPath.User_Online_Count)
|
||||
@HttpMethod("POST")
|
||||
public class GetUserOnlineCountAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
int count = messagesStore.getOnlineUserCount();
|
||||
GetOnlineUserCountResult result = new GetOnlineUserCountResult();
|
||||
GetOnlineUserCountResult.Node node = new GetOnlineUserCountResult.Node();
|
||||
node.node = 1;
|
||||
node.count = count;
|
||||
result.add(node);
|
||||
|
||||
setResponseContent(RestResult.ok(result), response);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.GetUserSessionResult;
|
||||
import cn.wildfirechat.pojos.InputGetChatroomInfo;
|
||||
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.moquette.persistence.MemorySessionStore;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Route(APIPath.User_Session_List)
|
||||
@HttpMethod("POST")
|
||||
public class GetUserSessionsAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
InputUserId inputUserId = getRequestBody(request.getNettyRequest(), InputUserId.class);
|
||||
String userId = inputUserId.getUserId();
|
||||
if (!StringUtil.isNullOrEmpty(userId)) {
|
||||
Collection<MemorySessionStore.Session> sessions = sessionsStore.sessionForUser(userId);
|
||||
GetUserSessionResult result = new GetUserSessionResult();
|
||||
for (MemorySessionStore.Session session : sessions) {
|
||||
boolean isOnline = sessionsStore.isClientOnline(session.getClientID());
|
||||
result.userSessions.add(new GetUserSessionResult.UserSession(session.getUsername(), session.getClientID(), session.getPlatform(), session.getPushType(), session.getDeviceToken(), session.getVoipDeviceToken(), isOnline));
|
||||
}
|
||||
|
||||
setResponseContent(RestResult.ok(result), response);
|
||||
} else {
|
||||
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Executable
+37
@@ -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()) ||
|
||||
|
||||
+98
@@ -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));
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
package com.xiaoleilu.loServer.exception;
|
||||
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 设置异常
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class ServerSettingException extends RuntimeException{
|
||||
private static final long serialVersionUID = -4134588858314744501L;
|
||||
|
||||
public ServerSettingException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public ServerSettingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ServerSettingException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
public ServerSettingException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
public ServerSettingException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
}
|
||||
package com.xiaoleilu.loServer.exception;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 设置异常
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class ServerSettingException extends RuntimeException{
|
||||
private static final long serialVersionUID = -4134588858314744501L;
|
||||
|
||||
public ServerSettingException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public ServerSettingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ServerSettingException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
public ServerSettingException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
public ServerSettingException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import cn.hutool.core.lang.Singleton;
|
||||
import cn.wildfirechat.common.IMExceptionEvent;
|
||||
import com.xiaoleilu.hutool.lang.Singleton;
|
||||
import com.xiaoleilu.loServer.ServerSetting;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.action.UnknownErrorAction;
|
||||
@@ -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;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import com.xiaoleilu.hutool.lang.Singleton;
|
||||
import com.xiaoleilu.loServer.ServerSetting;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.action.FileAction;
|
||||
|
||||
+27
-28
@@ -1,28 +1,27 @@
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.FileRegion;
|
||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpContentCompressor;
|
||||
|
||||
/**
|
||||
* 解决大文件传输与Gzip压缩冲突问题
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class HttpChunkContentCompressor extends HttpContentCompressor {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
StaticLog.debug("Write object [{}]", msg);
|
||||
|
||||
if (msg instanceof FileRegion || msg instanceof DefaultHttpResponse) {
|
||||
//文件传输不经过Gzip压缩
|
||||
ctx.write(msg, promise);
|
||||
}else{
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import cn.hutool.log.StaticLog;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.FileRegion;
|
||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpContentCompressor;
|
||||
|
||||
/**
|
||||
* 解决大文件传输与Gzip压缩冲突问题
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class HttpChunkContentCompressor extends HttpContentCompressor {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
StaticLog.debug("Write object [{}]", msg);
|
||||
|
||||
if (msg instanceof FileRegion || msg instanceof DefaultHttpResponse) {
|
||||
//文件传输不经过Gzip压缩
|
||||
ctx.write(msg, promise);
|
||||
}else{
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import com.xiaoleilu.hutool.util.FileUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.xiaoleilu.loServer.handler;
|
||||
|
||||
import com.xiaoleilu.hutool.lang.Singleton;
|
||||
import com.xiaoleilu.loServer.ServerSetting;
|
||||
import com.xiaoleilu.loServer.action.Action;
|
||||
import com.xiaoleilu.loServer.action.FileAction;
|
||||
|
||||
@@ -10,15 +10,12 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.xiaoleilu.hutool.http.HttpUtil;
|
||||
import com.xiaoleilu.hutool.lang.Conver;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.CharsetUtil;
|
||||
import com.xiaoleilu.hutool.util.DateUtil;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import com.xiaoleilu.hutool.util.URLUtil;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
@@ -261,7 +258,7 @@ public class Request {
|
||||
* @return 获得Integer类型请求参数
|
||||
*/
|
||||
public Integer getIntParam(String name, Integer defaultValue) {
|
||||
return Conver.toInt(getParam(name), defaultValue);
|
||||
return Convert.toInt(getParam(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +267,7 @@ public class Request {
|
||||
* @return 获得long类型请求参数
|
||||
*/
|
||||
public Long getLongParam(String name, Long defaultValue) {
|
||||
return Conver.toLong(getParam(name), defaultValue);
|
||||
return Convert.toLong(getParam(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,7 +276,7 @@ public class Request {
|
||||
* @return 获得Double类型请求参数
|
||||
*/
|
||||
public Double getDoubleParam(String name, Double defaultValue) {
|
||||
return Conver.toDouble(getParam(name), defaultValue);
|
||||
return Convert.toDouble(getParam(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,7 +285,7 @@ public class Request {
|
||||
* @return 获得Float类型请求参数
|
||||
*/
|
||||
public Float getFloatParam(String name, Float defaultValue) {
|
||||
return Conver.toFloat(getParam(name), defaultValue);
|
||||
return Convert.toFloat(getParam(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,7 +294,7 @@ public class Request {
|
||||
* @return 获得Boolean类型请求参数
|
||||
*/
|
||||
public Boolean getBoolParam(String name, Boolean defaultValue) {
|
||||
return Conver.toBool(getParam(name), defaultValue);
|
||||
return Convert.toBool(getParam(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,7 +474,7 @@ public class Request {
|
||||
protected void putIp(ChannelHandlerContext ctx) {
|
||||
String ip = getHeader("X-Forwarded-For");
|
||||
if (StrUtil.isNotBlank(ip)) {
|
||||
ip = HttpUtil.getMultistageReverseProxyIp(ip);
|
||||
ip = NetUtil.getMultistageReverseProxyIp(ip);
|
||||
} else {
|
||||
final InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
|
||||
ip = insocket.getAddress().getHostAddress();
|
||||
|
||||
@@ -13,12 +13,9 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.xiaoleilu.hutool.http.HttpUtil;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
import com.xiaoleilu.hutool.util.CharsetUtil;
|
||||
import com.xiaoleilu.hutool.util.DateUtil;
|
||||
import com.xiaoleilu.hutool.util.StrUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.xiaoleilu.loServer.ServerSetting;
|
||||
import com.xiaoleilu.loServer.listener.FileProgressiveFutureListener;
|
||||
|
||||
@@ -44,6 +41,8 @@ import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
|
||||
import org.apache.tika.Tika;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static cn.hutool.core.date.DatePattern.HTTP_DATETIME_PATTERN;
|
||||
|
||||
/**
|
||||
* 响应对象
|
||||
*
|
||||
@@ -332,7 +331,7 @@ public class Response {
|
||||
* @param httpCacheSeconds 缓存时间,单位秒
|
||||
*/
|
||||
public void setDateAndCache(long lastModify, int httpCacheSeconds) {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(DateUtil.HTTP_DATETIME_PATTERN, Locale.US);
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);
|
||||
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
|
||||
// Date header
|
||||
|
||||
+1
-4
@@ -2,10 +2,7 @@ package com.xiaoleilu.loServer.listener;
|
||||
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import com.xiaoleilu.hutool.io.IoUtil;
|
||||
import com.xiaoleilu.hutool.log.Log;
|
||||
import com.xiaoleilu.hutool.log.StaticLog;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import io.netty.channel.ChannelProgressiveFuture;
|
||||
import io.netty.channel.ChannelProgressiveFutureListener;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -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,8 +112,13 @@ 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";
|
||||
|
||||
|
||||
public static final String SENSITIVE_Filter_Type = "sensitive.filter.type";
|
||||
|
||||
@@ -122,11 +129,13 @@ 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";
|
||||
public static final String SERVER_MULTI_PAD_ENDPOINT = "server.multi_pad_endpoint";
|
||||
public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification";
|
||||
public static final String SERVER_MOBILE_DEFAULT_SILENT_WHEN_PC_ONLINE = "server.mobile_default_silent_when_pc_online";
|
||||
public static final String SERVER_CLIENT_SUPPORT_KICKOFF_EVENT = "server.client_support_kickoff_event";
|
||||
@@ -139,32 +148,45 @@ 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";
|
||||
|
||||
public static final String MESSAGE_NO_Forward_Admin_Message = "message.no_forward_admin_message";
|
||||
|
||||
public static final String MESSAGE_Push_Expired_Days = "message.push_expired_days";
|
||||
|
||||
public static final String MESSAGE_Forward_With_Client_Info = "message.forward_with_client_info";
|
||||
|
||||
public static final String BROADCAST_Target_From_User_Table = "message.broadcast.target_from_user_table";
|
||||
|
||||
public static final String ROBOT_Callback_With_Client_Info = "robot.callback_with_client_info";
|
||||
public static final String CHANNEL_Callback_With_Client_Info = "channel.callback_with_client_info";
|
||||
|
||||
public static final String FRIEND_Disable_Search = "friend.disable_search";
|
||||
public static final String FRIEND_Disable_NickName_Search = "friend.disable_nick_name_search";
|
||||
public static final String FRIEND_Disable_UserId_Search = "friend.disable_user_id_search";
|
||||
public static final String FRIEND_Disable_Friend_Request = "friend.disable_friend_request";
|
||||
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_New_Welcome_Message = "friend.new_welcome_message";
|
||||
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";
|
||||
public static final String CHATROOM_Create_When_Not_Exist = "chatroom.create_when_not_exist";
|
||||
public static final String CHATROOM_Kickoff_Other_Platform = "chatroom.kickoff_other_platform";
|
||||
|
||||
|
||||
public static final String GROUP_Allow_Owner_Recall_Self_Msg = "group.allow_owner_recall_self_msg";
|
||||
public static final String GROUP_Allow_Manager_Recall_Self_Msg = "group.allow_manager_recall_self_msg";
|
||||
public static final String GROUP_Allow_Client_Custom_Operation_Notification = "group.allow_client_custom_operation_notification";
|
||||
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 GROUP_Disable_Stranger_Invite = "group.disable_stranger_invite";
|
||||
|
||||
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";
|
||||
@@ -188,6 +210,9 @@ public final class BrokerConstants {
|
||||
public static final String HTTP_CHANNEL_RATE_LIMIT = "http.channel.rate_limit";
|
||||
public static final String CLIENT_REQUEST_RATE_LIMIT = "client.request_rate_limit";
|
||||
|
||||
public static final String HTTP_CLOSE_API_VERSION = "http.close_api_version";
|
||||
|
||||
|
||||
private BrokerConstants() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,24 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
|
||||
ErrorCode errorCode = m_messagesStore.canAddGroupMembers(fromUser, request.getGroup().getMembersList());
|
||||
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
|
||||
WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin);
|
||||
if (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 <heavyrain.lee@gmail.com>
|
||||
*
|
||||
* 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 <heavyrain.lee@gmail.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ package io.moquette.imhandler;
|
||||
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.xiaoleilu.hutool.system.UserInfo;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.moquette.spi.impl.security.TokenAuthenticator;
|
||||
|
||||
@@ -10,12 +10,10 @@ package io.moquette.imhandler;
|
||||
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import win.liyufan.im.I18n;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.MessageShardingUtil;
|
||||
|
||||
@@ -43,17 +41,8 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
|
||||
saveAndPublish(request.getTargetUid(), null, builder.build(), requestSourceType);
|
||||
}
|
||||
|
||||
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
|
||||
String language = "zh_CN";
|
||||
if (session != null && !StringUtil.isNullOrEmpty(session.getLanguage())) {
|
||||
language = session.getLanguage();
|
||||
}
|
||||
WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
|
||||
if (m_messagesStore.isNewFriendWelcomeMessage()) {
|
||||
contentBuilder.setType(92);
|
||||
} else {
|
||||
contentBuilder.setType(90).setContent(I18n.getString(language, "Above_Greeting_Message"));
|
||||
}
|
||||
contentBuilder.setType(92);
|
||||
|
||||
builder = WFCMessage.Message.newBuilder();
|
||||
builder.setFromUser(request.getTargetUid());
|
||||
@@ -64,13 +53,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
|
||||
messageId = MessageShardingUtil.generateId();
|
||||
builder.setMessageId(messageId);
|
||||
saveAndPublish(request.getTargetUid(), null, builder.build(), requestSourceType);
|
||||
|
||||
if (m_messagesStore.isNewFriendWelcomeMessage()) {
|
||||
contentBuilder.setType(93);
|
||||
} else {
|
||||
contentBuilder.setContent(I18n.getString(language, "Friend_Can_Start_Chat"));
|
||||
}
|
||||
|
||||
contentBuilder.setType(93);
|
||||
builder.setContent(contentBuilder);
|
||||
messageId = MessageShardingUtil.generateId();
|
||||
builder.setMessageId(messageId);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -12,7 +12,6 @@ import cn.wildfirechat.pojos.SystemSettingPojo;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import cn.wildfirechat.server.ThreadPoolExecutorWrapper;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.core.MultiMap;
|
||||
import com.hazelcast.util.StringUtil;
|
||||
@@ -39,6 +38,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 +161,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> searchUserByNameMobileUserId(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 +179,42 @@ 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";
|
||||
|
||||
|
||||
sql += " and _type <> 2"; //can search normal user(0) and robot(1) and admin(100), can not search things
|
||||
|
||||
if (searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
|
||||
sql += " limit 1";
|
||||
int sqlParaCount = 1;
|
||||
if(searchType == SearchUserType_Name) {
|
||||
sql += " where `_name` = ? ";
|
||||
} else if(searchType == SearchUserType_Mobile) {
|
||||
sql += " where `_mobile` = ? ";
|
||||
} else if(searchType == SearchUserType_UserId) {
|
||||
sql += " where `_uid` = ? ";
|
||||
} else if(searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name_Mobile_DisplayName) {
|
||||
sqlParaCount = 2;
|
||||
sql += " where (`_name` = ? or `_mobile` = ?) ";
|
||||
} else {
|
||||
sql += " limit 20";
|
||||
sqlParaCount = 3;
|
||||
sql += " where (`_name` = ? or `_mobile` = ? or `_uid` = ?) ";
|
||||
}
|
||||
|
||||
if (page > 0) {
|
||||
sql += " offset " + page * 20;
|
||||
|
||||
sql += " and `_type` <> 2 and `_deleted` = 0"; //can search normal user(0) and robot(1) and admin(100), can not search things
|
||||
|
||||
if(searchType == SearchUserType_Name || searchType == SearchUserType_Mobile || searchType == SearchUserType_UserId) {
|
||||
sql += " limit 1";
|
||||
} else if(searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name_Mobile_DisplayName) {
|
||||
sql += " limit 2";
|
||||
} else {
|
||||
sql += " limit 3";
|
||||
}
|
||||
|
||||
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;
|
||||
for (int i = 0; i < sqlParaCount; i++) {
|
||||
statement.setString(i+1, 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 +262,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 +276,258 @@ 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_Name_Mobile || searchType == SearchUserType_Name_Mobile_DisplayName) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
|
||||
if(keyword.equals(user.getName())) {
|
||||
if(keyword.equals(user.getMobile()) && keyword.equals(user.getUid())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getMobile())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getUid())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
if (searchType == SearchUserType_Mobile) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
} else if(searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name_Mobile_DisplayName) {
|
||||
if(keyword.equals(user.getMobile())) {
|
||||
if(!keyword.equals(user.getName())) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
} else if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
|
||||
if(keyword.equals(user.getMobile())) {
|
||||
if(keyword.equals(user.getName()) && keyword.equals(user.getUid())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getName())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getUid())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchUserIdMask) > 0) {
|
||||
if (searchType == SearchUserType_UserId) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
} else if(searchType == SearchUserType_Name_Mobile_UserId) {
|
||||
if(keyword.equals(user.getUid())) {
|
||||
if(keyword.equals(user.getName()) && keyword.equals(user.getMobile())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0 && (value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getName())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchNameMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else if(keyword.equals(user.getMobile())) {
|
||||
if((value & ProtoConstants.DisableSearchMask.DisableSearchMobileMask) > 0) {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
filter.add(user);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ? ESCAPE '!' 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());
|
||||
}
|
||||
|
||||
keyword = keyword
|
||||
.replace("!", "!!")
|
||||
.replace("%", "!%")
|
||||
.replace("_", "!_")
|
||||
.replace("[", "![");
|
||||
|
||||
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 = searchUserByNameMobileUserId(keyword, searchType);
|
||||
List<WFCMessage.User> out = new ArrayList<>();
|
||||
if(page == 0) {
|
||||
out.addAll(nameOrIdMatched);
|
||||
}
|
||||
|
||||
if(searchType == SearchUserType_General || searchType == SearchUserType_Name_Mobile_DisplayName) {
|
||||
List<WFCMessage.User> general = searchUserByDisplayName(keyword, page, nameOrIdMatched);
|
||||
general.removeAll(nameOrIdMatched);
|
||||
out.addAll(general);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -815,7 +1045,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 +1083,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 +1145,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 +1160,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 +1176,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 +1732,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 +1759,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());
|
||||
}
|
||||
@@ -1571,10 +1798,12 @@ public class DatabaseStore {
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql;
|
||||
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX) {
|
||||
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX || platform == ProtoConstants.Platform.Platform_HarmonyPC) {
|
||||
sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0";
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Android || platform == ProtoConstants.Platform.Platform_Harmony) {
|
||||
sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0";
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iPad || platform == ProtoConstants.Platform.Platform_APad || platform == ProtoConstants.Platform.Platform_HarmonyPad) {
|
||||
sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0";
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Android) {
|
||||
sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0";
|
||||
} else {
|
||||
sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and `_platform` = ? and `_cid` <> ? and `_deleted` = 0";
|
||||
}
|
||||
@@ -1589,13 +1818,19 @@ public class DatabaseStore {
|
||||
|
||||
statement.setString(index++, uid);
|
||||
|
||||
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX) {
|
||||
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX || platform == ProtoConstants.Platform.Platform_HarmonyPC) {
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_Windows);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_OSX);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_LINUX);
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Android) {
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_HarmonyPC);
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Android || platform == ProtoConstants.Platform.Platform_Harmony) {
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_iOS);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_Android);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_Harmony);
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iPad || platform == ProtoConstants.Platform.Platform_APad || platform == ProtoConstants.Platform.Platform_HarmonyPad) {
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_iPad);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_APad);
|
||||
statement.setInt(index++, ProtoConstants.Platform.Platform_HarmonyPad);
|
||||
} else {
|
||||
statement.setInt(index++, platform);
|
||||
}
|
||||
@@ -1712,6 +1947,74 @@ public class DatabaseStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> getUserGroupIds(String userId, List<Integer> memberTypes) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql = "select _gid from t_group_member where _mid = ? ";
|
||||
if(!memberTypes.isEmpty()) {
|
||||
sql += " and _type in (";
|
||||
for (int i = 0; i < memberTypes.size(); i++) {
|
||||
if(i > 0) {
|
||||
sql += ",";
|
||||
}
|
||||
sql += memberTypes.get(i);
|
||||
}
|
||||
sql += ")";
|
||||
}
|
||||
statement = connection.prepareStatement(sql);
|
||||
|
||||
statement.setString(1, userId);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 +2688,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,17 +2917,117 @@ public class DatabaseStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> getAllEnds() {
|
||||
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(boolean fromUserTable) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
connection = DBUtil.getConnection();
|
||||
String sql = "select distinct(`_uid`) from t_user_session where `_deleted` = 0";
|
||||
String sql;
|
||||
if(fromUserTable) {
|
||||
sql = "select distinct(`_uid`) from t_user_session";
|
||||
} else {
|
||||
sql = "select distinct(`_uid`) from t_user where `_deleted` = 0 and `_type` <> 1 and `_type` <> 2";
|
||||
}
|
||||
statement = connection.prepareStatement(sql);
|
||||
|
||||
|
||||
|
||||
rs = statement.executeQuery();
|
||||
Set<String> out = new HashSet<>();
|
||||
while (rs.next()) {
|
||||
@@ -3246,7 +3645,7 @@ public class DatabaseStore {
|
||||
", `_extra`" +
|
||||
", `_dt` from t_channel";
|
||||
if (buzzy) {
|
||||
sql += " where `_name` like ?";
|
||||
sql += " where `_name` like ? ESCAPE '!' ";
|
||||
} else {
|
||||
sql += " where `_name` = ?";
|
||||
}
|
||||
@@ -3260,6 +3659,12 @@ public class DatabaseStore {
|
||||
sql += " offset " + page * 20;
|
||||
}
|
||||
|
||||
keyword = keyword
|
||||
.replace("!", "!!")
|
||||
.replace("%", "!%")
|
||||
.replace("_", "!_")
|
||||
.replace("[", "![");
|
||||
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
if (buzzy) {
|
||||
@@ -3316,47 +3721,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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,7 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
|
||||
private boolean supportMultiEndpoint = false;
|
||||
private boolean supportMultiPCEndpoint = false;
|
||||
private boolean supportMultiPadEndpoint = false;
|
||||
private boolean clientSupportKickoff = false;
|
||||
|
||||
public static class Session implements Comparable<Session>{
|
||||
@@ -292,6 +293,10 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
supportMultiPCEndpoint = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_PC_ENDPOINT, "false"));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
supportMultiPadEndpoint = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_PAD_ENDPOINT, "false"));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
try {
|
||||
clientSupportKickoff = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_CLIENT_SUPPORT_KICKOFF_EVENT, "false"));
|
||||
@@ -396,6 +401,10 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
&& !(platform == ProtoConstants.Platform.Platform_Windows && supportMultiPCEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_LINUX && supportMultiPCEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_OSX && supportMultiPCEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_HarmonyPC && supportMultiPCEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_iPad && supportMultiPadEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_APad && supportMultiPadEndpoint)
|
||||
&& !(platform == ProtoConstants.Platform.Platform_HarmonyPad && supportMultiPadEndpoint)
|
||||
) {
|
||||
databaseStore.clearMultiEndpoint(username, clientID, platform);
|
||||
if (userSessions.get(username) != null) {
|
||||
@@ -410,15 +419,19 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
}
|
||||
|
||||
boolean remove = false;
|
||||
if (platform == ProtoConstants.Platform.Platform_Android || platform == ProtoConstants.Platform.Platform_iOS) {
|
||||
if (s.getPlatform() == ProtoConstants.Platform.Platform_Android || s.getPlatform() == ProtoConstants.Platform.Platform_iOS) {
|
||||
if (platform == ProtoConstants.Platform.Platform_Android || platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Harmony) {
|
||||
if (s.getPlatform() == ProtoConstants.Platform.Platform_Android || s.getPlatform() == ProtoConstants.Platform.Platform_iOS || s.getPlatform() == ProtoConstants.Platform.Platform_Harmony) {
|
||||
remove = true;
|
||||
}
|
||||
} else if(platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_LINUX) {
|
||||
if (s.getPlatform() == ProtoConstants.Platform.Platform_OSX || s.getPlatform() == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_LINUX) {
|
||||
} else if(platform == ProtoConstants.Platform.Platform_iPad || platform == ProtoConstants.Platform.Platform_APad || platform == ProtoConstants.Platform.Platform_HarmonyPad) {
|
||||
if (s.getPlatform() == ProtoConstants.Platform.Platform_iPad || s.getPlatform() == ProtoConstants.Platform.Platform_APad || s.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad) {
|
||||
remove = true;
|
||||
}
|
||||
} else {
|
||||
} else if(platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_LINUX || platform == ProtoConstants.Platform.Platform_HarmonyPC) {
|
||||
if (s.getPlatform() == ProtoConstants.Platform.Platform_OSX || s.getPlatform() == ProtoConstants.Platform.Platform_Windows || s.getPlatform() == ProtoConstants.Platform.Platform_LINUX || s.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPC) {
|
||||
remove = true;
|
||||
}
|
||||
} else { //web, microapp
|
||||
if (s.getPlatform() ==platform) {
|
||||
remove = true;
|
||||
}
|
||||
@@ -615,6 +628,11 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClientOnline(String clientId) {
|
||||
return mServer.getProcessor().getConnectionDescriptors().isConnected(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredMessage inFlightAck(String clientID, int messageID) {
|
||||
return getSession(clientID).outboundFlightMessages.remove(messageID);
|
||||
@@ -742,7 +760,12 @@ public class MemorySessionStore implements ISessionsStore {
|
||||
if (session.getPlatform() == ProtoConstants.Platform.Platform_LINUX
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_WEB
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_Windows
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_OSX) {
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_OSX
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPC
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_iPad
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_APad
|
||||
|| session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad
|
||||
) {
|
||||
databaseStore.updateSessionDeleted(operator, pcClientId, 1);
|
||||
sessions.remove(pcClientId);
|
||||
mServer.getProcessor().kickoffSession(session);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -369,7 +357,11 @@ public class Server {
|
||||
private String getServerIp(IConfig config) {
|
||||
String serverIp = config.getProperty(BrokerConstants.SERVER_IP_PROPERTY_NAME);
|
||||
if (serverIp == null || serverIp.equals("0.0.0.0")) {
|
||||
serverIp = Utility.getLocalAddress().getHostAddress();
|
||||
if(Utility.getLocalAddress() != null) {
|
||||
serverIp = Utility.getLocalAddress().getHostAddress();
|
||||
} else {
|
||||
serverIp = "0.0.0.0";
|
||||
}
|
||||
}
|
||||
return serverIp;
|
||||
}
|
||||
@@ -378,7 +370,7 @@ public class Server {
|
||||
LOG.info("Configuring embedded Hazelcast instance");
|
||||
|
||||
serverIp = getServerIp(config);
|
||||
String hzConfigPath = "config/hazelcast.xml";
|
||||
String hzConfigPath = System.getProperty("hazelcast.configuration", "config/hazelcast.xml");
|
||||
if (hzConfigPath != null) {
|
||||
boolean isHzConfigOnClasspath = this.getClass().getClassLoader().getResource(hzConfigPath) != null;
|
||||
Config hzconfig = isHzConfigOnClasspath
|
||||
@@ -393,9 +385,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 {
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
|
||||
package io.moquette.spi;
|
||||
|
||||
import cn.wildfirechat.pojos.InputOutputUserInfo;
|
||||
import cn.wildfirechat.pojos.SystemSettingPojo;
|
||||
import cn.wildfirechat.pojos.*;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.xiaoleilu.loServer.model.FriendData;
|
||||
import cn.wildfirechat.pojos.InputOutputUserBlockStatus;
|
||||
import io.moquette.persistence.DatabaseStore;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.moquette.persistence.UserClientEntry;
|
||||
@@ -31,10 +29,7 @@ import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.mqtt.MqttQoS;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Defines the SPI to be implemented by a StorageService that handle persistence of messages
|
||||
@@ -107,18 +102,21 @@ public interface IMessagesStore {
|
||||
WFCMessage.PullMessageResult fetchMessage(String user, String exceptClientId, long fromMessageId, int pullType);
|
||||
WFCMessage.PullMessageResult loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count, Collection<Integer> contentTypes);
|
||||
long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String userId, long messageId, boolean directing);
|
||||
ErrorCode canAddGroupMembers(String operator, List<WFCMessage.GroupMember> memberList);
|
||||
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin);
|
||||
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra);
|
||||
ErrorCode 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> getUserGroupIds(String userId, List<Integer> types);
|
||||
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 +125,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);
|
||||
@@ -149,7 +147,7 @@ public interface IMessagesStore {
|
||||
List<InputOutputUserBlockStatus> getUserStatusList();
|
||||
|
||||
ErrorCode updateUserInfo(InputOutputUserInfo userInfo, int flag);
|
||||
void addUserInfo(WFCMessage.User user, String password) throws Exception;
|
||||
void addUserInfo(WFCMessage.User user) throws Exception;
|
||||
void destroyUser(String userId);
|
||||
void updateUserInfo(WFCMessage.User user) throws Exception;
|
||||
WFCMessage.User getUserInfo(String userId);
|
||||
@@ -157,6 +155,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);
|
||||
@@ -169,6 +169,7 @@ public interface IMessagesStore {
|
||||
|
||||
long insertChatroomMessages(String target, int line, long messageId);
|
||||
Collection<UserClientEntry> getChatroomMembers(String chatroomId);
|
||||
OutputUserChatroom getUserChatroom(String userId);
|
||||
WFCMessage.PullMessageResult fetchChatroomMessage(String fromUser, String chatroomId, String exceptClientId, long fromMessageId);
|
||||
|
||||
ErrorCode verifyToken(String userId, String token, List<String> serverIPs, List<Integer> ports);
|
||||
@@ -179,7 +180,6 @@ public interface IMessagesStore {
|
||||
|
||||
ErrorCode saveAddFriendRequest(String userId, WFCMessage.AddFriendRequest request, long[] head, boolean isAdmin);
|
||||
ErrorCode handleFriendRequest(String userId, WFCMessage.HandleFriendRequest request, WFCMessage.Message.Builder msgBuilder, long[] heads, boolean isAdmin);
|
||||
boolean isNewFriendWelcomeMessage();
|
||||
ErrorCode deleteFriend(String userId, String friendUid, long[] head);
|
||||
ErrorCode blackUserRequest(String fromUser, String targetUserId, int status, long[] head);
|
||||
FriendData getFriendData(String fromUser, String targetUserId);
|
||||
@@ -216,12 +216,16 @@ 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);
|
||||
boolean checkUserInChannel(String user, String channelId);
|
||||
Collection<String> getChannelSubscriber(String channelId);
|
||||
|
||||
int getOnlineUserCount();
|
||||
GetOnlineUserResult getOnlineUsers(int offset, int count);
|
||||
|
||||
Set<String> handleSensitiveWord(String message);
|
||||
boolean addSensitiveWords(List<String> words);
|
||||
boolean removeSensitiveWords(List<String> words);
|
||||
@@ -233,10 +237,16 @@ public interface IMessagesStore {
|
||||
boolean isAllowRobotCustomGroupNotification();
|
||||
int getVisibleQuitKickoffNotification();
|
||||
|
||||
int getGroupForbiddenClientOperation();
|
||||
|
||||
boolean isForwardMessageWithClientInfo();
|
||||
boolean isRobotCallbackWithClientInfo();
|
||||
boolean isChannelCallbackWithClientInfo();
|
||||
|
||||
boolean isRobotAutoAcceptFriendRequest();
|
||||
|
||||
long getPushExpiredTimes();
|
||||
|
||||
List<Integer> getClientForbiddenSendTypes();
|
||||
List<Integer> getBlackListExceptionTypes();
|
||||
List<Integer> getGroupMuteExceptionTypes();
|
||||
@@ -249,6 +259,9 @@ public interface IMessagesStore {
|
||||
|
||||
//使用了数据库,会比较慢,仅能用户用户/群组等id的生成
|
||||
String getShortUUID();
|
||||
|
||||
boolean checkSignature(String signature);
|
||||
boolean existSignatures();
|
||||
/**
|
||||
* Used to initialize all persistent store structures
|
||||
*/
|
||||
|
||||
@@ -74,6 +74,8 @@ public interface ISessionsStore {
|
||||
*/
|
||||
Collection<ClientSession> getAllSessions();
|
||||
|
||||
boolean isClientOnline(String clientId);
|
||||
|
||||
StoredMessage inFlightAck(String clientID, int messageID);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
@@ -223,7 +223,12 @@ public class MessagesPublisher {
|
||||
if (targetSession.getPlatform() == ProtoConstants.Platform.Platform_WEB
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_Windows
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_LINUX
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_OSX) {
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_OSX
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPC
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_iPad
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_APad
|
||||
|| targetSession.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad
|
||||
) {
|
||||
boolean targetIsActive = this.connectionDescriptors.isConnected(targetSession.getClientSession().clientID);
|
||||
if (targetIsActive) {
|
||||
isPcOnline = true;
|
||||
@@ -235,7 +240,7 @@ public class MessagesPublisher {
|
||||
|
||||
for (Session targetSession : sessions) {
|
||||
//超过7天不活跃的用户忽略
|
||||
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > 7 * 24 * 60 * 60 * 1000) {
|
||||
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > m_messagesStore.getPushExpiredTimes()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -386,10 +391,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 +416,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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -457,14 +474,44 @@ public class MessagesPublisher {
|
||||
LOG.info("the target {} of user {} is not active", targetSession.getClientID(), targetSession.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
if(sessions.isEmpty() && message.getContent().getType() == 403 && !user.equals(message.getFromUser())) {
|
||||
WFCMessage.User userInfo = m_messagesStore.getUserInfo(user);
|
||||
if (userInfo != null && userInfo.getType() == ProtoConstants.UserType.UserType_Robot) {
|
||||
WFCMessage.Robot robot = m_messagesStore.getRobot(user);
|
||||
if (robot != null && !StringUtil.isNullOrEmpty(robot.getCallback())) {
|
||||
OutputClient outputClient = null;
|
||||
if(m_messagesStore.isRobotCallbackWithClientInfo() && !StringUtil.isNullOrEmpty(exceptClientId)) {
|
||||
Session session = m_sessionsStore.getSession(exceptClientId);
|
||||
if(session != null && session.getUsername().equals(message.getFromUser())) {
|
||||
outputClient = new OutputClient(session.getPlatform(), exceptClientId);
|
||||
}
|
||||
}
|
||||
|
||||
final WFCMessage.Message finalMsg = message;
|
||||
OutputClient finalOutputClient = outputClient;
|
||||
Server.getServer().getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(robot.getCallback(), GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(finalMsg, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Robot_Message_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 +523,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();
|
||||
}
|
||||
}
|
||||
@@ -652,6 +710,8 @@ public class MessagesPublisher {
|
||||
pushContent = "[文件]";
|
||||
} else if(type == ProtoConstants.ContentType.Sticker) {
|
||||
pushContent = "[表情]";
|
||||
} else if (type == ProtoConstants.ContentType.Name_Card) {
|
||||
pushContent = "[名片]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package io.moquette.spi.impl;
|
||||
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.pojos.OutputCheckUserOnline;
|
||||
import cn.wildfirechat.pojos.UserOnlineStatus;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
@@ -48,6 +49,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 +109,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();
|
||||
@@ -265,7 +267,27 @@ public class ProtocolProcessor {
|
||||
if (!StringUtil.isNullOrEmpty(mUserOnlineStatusCallback)) {
|
||||
mServer.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mUserOnlineStatusCallback, GsonUtil.gson.toJson(new UserOnlineStatus(userId, clientId, platform, status, packageName)), HttpUtils.HttpPostType.POST_TYPE_User_Online_Event_Callback);
|
||||
int sessionstatus;
|
||||
Collection<MemorySessionStore.Session> useSessions = m_sessionsStore.sessionForUser(userId);
|
||||
UserOnlineStatus userOnlineStatus = new UserOnlineStatus(userId, clientId, platform, status, packageName);
|
||||
userOnlineStatus.sessions = new ArrayList<>();
|
||||
|
||||
for (MemorySessionStore.Session session : useSessions) {
|
||||
if (session.getDeleted() > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
|
||||
if (descriptor == null) {
|
||||
sessionstatus = 1;
|
||||
} else {
|
||||
sessionstatus = 0;
|
||||
}
|
||||
|
||||
userOnlineStatus.sessions.add(new OutputCheckUserOnline.Session(userId, session.getClientID(), session.getPlatform(), sessionstatus, session.getLastActiveTime(), session.getAppName()));
|
||||
}
|
||||
|
||||
HttpUtils.httpJsonPost(mUserOnlineStatusCallback, GsonUtil.gson.toJson(userOnlineStatus), HttpUtils.HttpPostType.POST_TYPE_User_Online_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -339,6 +361,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 +486,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 +629,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 +672,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,6 +752,10 @@ public class ProtocolProcessor {
|
||||
channel.flush();
|
||||
}
|
||||
|
||||
public ConnectionDescriptorStore getConnectionDescriptors() {
|
||||
return connectionDescriptors;
|
||||
}
|
||||
|
||||
public void addInterceptHandler(InterceptHandler interceptHandler) {
|
||||
this.m_interceptor.addInterceptHandler(interceptHandler);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.server.ThreadPoolExecutorWrapper;
|
||||
import com.google.gson.Gson;
|
||||
@@ -92,7 +93,7 @@ public class Qos1PublishHandler extends QosPublishHandler {
|
||||
for (Class cls:ClassUtil.getAllAssignedClass(IMHandler.class)) {
|
||||
Handler annotation = (Handler)cls.getAnnotation(Handler.class);
|
||||
if(annotation != null) {
|
||||
IMHandler handler = (IMHandler) com.xiaoleilu.hutool.util.ClassUtil.newInstance(cls);
|
||||
IMHandler handler = (IMHandler) ReflectUtil.newInstance(cls);
|
||||
m_imHandlers.put(annotation.value(), handler);
|
||||
}
|
||||
}
|
||||
@@ -140,7 +141,7 @@ public class Qos1PublishHandler extends QosPublishHandler {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
out.addSession(userId, session.getClientID(), session.getPlatform(), status, session.getLastActiveTime());
|
||||
out.addSession(userId, session.getClientID(), session.getPlatform(), status, session.getLastActiveTime(), session.getAppName());
|
||||
}
|
||||
|
||||
callback.onRouteHandled(GsonUtil.gson.toJson(out).getBytes());
|
||||
@@ -243,15 +244,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||
import io.moquette.BrokerConstants;
|
||||
import io.moquette.server.config.IConfig;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.flywaydb.core.api.configuration.FlywayConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -50,6 +49,7 @@ public class DBUtil {
|
||||
|
||||
public static void init(IConfig config) {
|
||||
String embedDB = config.getProperty(BrokerConstants.EMBED_DB_PROPERTY_NAME);
|
||||
String h2dbPath = config.getProperty(BrokerConstants.H2DB_PATH, "./h2db/wfchat");
|
||||
boolean autoCleanMsgs = "true".equals(config.getProperty(BrokerConstants.DB_AUTO_CLEAN_HISTORY_MESSAGES));
|
||||
if (embedDB != null && embedDB.equals("1")) {
|
||||
IsEmbedDB = true;
|
||||
@@ -68,7 +68,7 @@ public class DBUtil {
|
||||
migrateLocation = "filesystem:./migrate/h2";
|
||||
comboPooledDataSource = new ComboPooledDataSource();
|
||||
|
||||
comboPooledDataSource.setJdbcUrl( "jdbc:h2:./h2db/wfchat;AUTO_SERVER=TRUE;MODE=MySQL" );
|
||||
comboPooledDataSource.setJdbcUrl( "jdbc:h2:" + h2dbPath + ";AUTO_SERVER=TRUE;MODE=MySQL" );
|
||||
comboPooledDataSource.setUser("SA");
|
||||
comboPooledDataSource.setPassword("SA");
|
||||
comboPooledDataSource.setMinPoolSize(5);
|
||||
@@ -116,6 +116,27 @@ public class DBUtil {
|
||||
} else if(flyway.info().current().getVersion().getMajor().intValue() < 43) {
|
||||
System.out.println("数据库执行升级需要较长时间,可能长达数分钟或更长,请耐心等待,不要中断。。。");
|
||||
}
|
||||
|
||||
if(flyway.info().current() != null && flyway.info().current().getVersion().getMajor().intValue() < 55) {
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
|
||||
String sql = "update flyway_schema_history set checksum = ? where version = ? and checksum = ?";
|
||||
|
||||
statement = connection.prepareStatement(sql);
|
||||
int index = 1;
|
||||
statement.setLong(index++, -931486413L);
|
||||
statement.setString(index++, "3");
|
||||
statement.setLong(index++, 478454046L);
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Utility.printExecption(LOG, e, RDBS_Exception);
|
||||
} finally {
|
||||
DBUtil.closeDB(connection, statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
flyway.migrate();
|
||||
|
||||
|
||||
@@ -68,7 +68,9 @@ public class GitRepositoryState {
|
||||
public static GitRepositoryState getGitRepositoryState() throws IOException {
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
InputStream inputStream = new FileInputStream("config/git.properties");
|
||||
String configPath = System.getProperty("wildfirechat.path", null);
|
||||
File f = new File(configPath, "config/git.properties");
|
||||
InputStream inputStream = new FileInputStream(f);
|
||||
BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
|
||||
properties.load(bf);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -87,8 +88,8 @@ public class HttpUtils {
|
||||
}
|
||||
System.out.println(logText);
|
||||
e.printStackTrace();
|
||||
LOG.info(logText);
|
||||
LOG.info("POST to {} with data {} failure", url, jsonStr);
|
||||
LOG.error(logText);
|
||||
LOG.error("POST to {} failed", url);
|
||||
if(httpCallback != null) {
|
||||
httpCallback.onFailure(-1, e.getMessage());
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package win.liyufan.im;
|
||||
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class I18n {
|
||||
private static ClassLoader Loader = null;
|
||||
static {
|
||||
String configPath = System.getProperty("wildfirechat.path", null);
|
||||
String resBundlePaht = "config/i18n";
|
||||
|
||||
File file = new File(configPath, resBundlePaht);
|
||||
URL[] urls = new URL[0];
|
||||
try {
|
||||
urls = new URL[]{file.toURI().toURL()};
|
||||
Loader = new URLClassLoader(urls);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, ResourceBundle> bundleMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static String getString(String language, String key) {
|
||||
ResourceBundle bundle = bundleMap.get(language);
|
||||
|
||||
if (StringUtil.isNullOrEmpty(language)) language = "zh_CN";
|
||||
|
||||
if (bundle == null) {
|
||||
bundle = ResourceBundle.getBundle("messages", new Locale(language), Loader);
|
||||
bundleMap.put(language, bundle);
|
||||
}
|
||||
|
||||
try {
|
||||
return bundle.getString(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "糟糕,字符串 " + key + " 没有找到";
|
||||
}
|
||||
|
||||
public static void test() throws MalformedURLException {
|
||||
|
||||
// 设置定制的语言国家代码
|
||||
Locale locale1 = new Locale("zh");
|
||||
Locale locale2 = new Locale("en");
|
||||
ResourceBundle rb = ResourceBundle.getBundle("messages", locale1, Loader);
|
||||
|
||||
|
||||
|
||||
// 获得相应的key值
|
||||
String greeting = rb.getString("Above_Greeting_Message");
|
||||
String userInfo = rb.getString("Friend_Can_Start_Chat");
|
||||
|
||||
System.out.println(greeting);
|
||||
System.out.println(userInfo);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<Properties>
|
||||
<!--自定义一些常量,之后使用${变量名}引用-->
|
||||
<Property name="MSG_LOG_HOME">./logs</Property>
|
||||
<Property name="logFileName">test.log</Property>
|
||||
<property name="charset">UTF-8</property>
|
||||
<!--自定义的输出格式-->
|
||||
<property name="pattern">%d %-5p [%t] %C{2} (%F:%L) - %m%n</property>
|
||||
@@ -21,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>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.95</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ public interface APIPath {
|
||||
String Chatroom_Destroy = "/admin/chatroom/del";
|
||||
String Chatroom_Info = "/admin/chatroom/info";
|
||||
String Chatroom_GetMembers = "/admin/chatroom/members";
|
||||
String Chatroom_GetUserChatroom = "/admin/chatroom/user_chatroom";
|
||||
String Chatroom_SetBlacklist = "/admin/chatroom/set_black_status";
|
||||
String Chatroom_GetBlacklist = "/admin/chatroom/get_black_status";
|
||||
String Chatroom_SetManager = "/admin/chatroom/set_manager";
|
||||
@@ -26,6 +27,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";
|
||||
@@ -35,6 +37,7 @@ public interface APIPath {
|
||||
String User_Kickoff_Client = "/admin/user/kickoff_client";
|
||||
String User_Online_Count = "/admin/user/online_count";
|
||||
String User_Online_List = "/admin/user/online_list";
|
||||
String User_Session_List = "/admin/user/session_list";
|
||||
String User_Application_Get_UserInfo = "/admin/user/app_get_user_info";
|
||||
|
||||
String Friend_Update_Status = "/admin/friend/status";
|
||||
@@ -68,6 +71,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";
|
||||
@@ -75,8 +79,10 @@ public interface APIPath {
|
||||
String Group_Mute_Member = "/admin/group/manager/mute";
|
||||
String Group_Allow_Member = "/admin/group/manager/allow";
|
||||
String Get_User_Groups = "/admin/group/of_user";
|
||||
String Get_User_Groups_By_Type = "/admin/group/of_user_by_type";
|
||||
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";
|
||||
@@ -85,13 +91,18 @@ public interface APIPath {
|
||||
String Check_User_Subscribe_Channel = "/admin/channel/is_subscribed";
|
||||
String Get_System_Setting = "/admin/system/get_setting";
|
||||
String Put_System_Setting = "/admin/system/put_setting";
|
||||
|
||||
String GET_CUSTOMER = "/admin/customer";
|
||||
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";
|
||||
@@ -99,11 +110,14 @@ 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";
|
||||
String Robot_Get_Profile = "/robot/profile";
|
||||
String Robot_Message_Send = "/robot/message/send";
|
||||
String Robot_Message_Recall = "/robot/message/recall";
|
||||
String Robot_Message_Update = "/robot/message/update";
|
||||
String Robot_Set_Callback = "/robot/set_callback";
|
||||
String Robot_Get_Callback = "/robot/get_callback";
|
||||
String Robot_Delete_Callback = "/robot/delete_callback";
|
||||
@@ -115,6 +129,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";
|
||||
@@ -123,4 +138,6 @@ public interface APIPath {
|
||||
String Robot_Group_Member_Quit = "/robot/group/member/quit";
|
||||
String Robot_Group_Transfer = "/robot/group/transfer";
|
||||
String Robot_Group_Set_Manager = "/robot/group/manager/set";
|
||||
|
||||
String Robot_Conference_Request = "/robot/conference/request";
|
||||
}
|
||||
|
||||
@@ -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,8 +62,12 @@ 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_OTHER_CLIENT_ALREADY_IN_CHATROOM(225, "other client already in chatroom"),
|
||||
|
||||
ERROR_CODE_CHANNEL_NO_EXIST(236, "channel no exist"),
|
||||
ERROR_CODE_CHANNEL_NO_SECRET(237, "channel no secret"),
|
||||
ERROR_CODE_USER_NOT_PREPARED(238, "user not prepared"),
|
||||
@@ -72,7 +77,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"),
|
||||
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
package cn.wildfirechat.messagecontentbuilder;
|
||||
|
||||
import cn.wildfirechat.pojos.MessagePayload;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ArticlesContentBuilder extends MessageContentBuilder{
|
||||
public static class Article {
|
||||
public String id;
|
||||
public String cover;
|
||||
public String title;
|
||||
public String digest;
|
||||
public String url;
|
||||
public boolean readReport;
|
||||
}
|
||||
public Article topArticle;
|
||||
public List<Article> subArticles;
|
||||
|
||||
public static ArticlesContentBuilder newBuilder(String id, String cover, String title, String digest, String url, boolean readReport) {
|
||||
ArticlesContentBuilder builder = new ArticlesContentBuilder();
|
||||
builder.topArticle = new Article();
|
||||
builder.topArticle.id = id;
|
||||
builder.topArticle.cover = cover;
|
||||
builder.topArticle.title = title;
|
||||
builder.topArticle.digest = digest;
|
||||
builder.topArticle.url = url;
|
||||
builder.topArticle.readReport = readReport;
|
||||
return builder;
|
||||
}
|
||||
|
||||
public ArticlesContentBuilder addSubArticle(String id, String cover, String title, String digest, String url, boolean readReport) {
|
||||
Article article = new Article();
|
||||
article.id = id;
|
||||
article.cover = cover;
|
||||
article.title = title;
|
||||
article.digest = digest;
|
||||
article.url = url;
|
||||
article.readReport = readReport;
|
||||
if(subArticles == null) {
|
||||
subArticles = new ArrayList<>();
|
||||
}
|
||||
subArticles.add(article);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static JSONObject toJSON(Article article) {
|
||||
JSONObject top = new JSONObject();
|
||||
if(!StringUtil.isNullOrEmpty(article.id))
|
||||
top.put("id", article.id);
|
||||
if(!StringUtil.isNullOrEmpty(article.cover))
|
||||
top.put("cover", article.cover);
|
||||
if(!StringUtil.isNullOrEmpty(article.title))
|
||||
top.put("title", article.title);
|
||||
if(!StringUtil.isNullOrEmpty(article.digest))
|
||||
top.put("digest", article.digest);
|
||||
if(!StringUtil.isNullOrEmpty(article.url))
|
||||
top.put("url", article.url);
|
||||
if(article.readReport)
|
||||
top.put("rr", article.readReport);
|
||||
return top;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessagePayload build() {
|
||||
MessagePayload payload = encodeBase();
|
||||
payload.setType(ProtoConstants.ContentType.Articles);
|
||||
payload.setPersistFlag(ProtoConstants.PersistFlag.Persist_And_Count);
|
||||
payload.setSearchableContent(topArticle.title);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("top", toJSON(topArticle));
|
||||
if(subArticles != null && !subArticles.isEmpty()) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
subArticles.forEach(article -> jsonArray.add(toJSON(article)));
|
||||
jsonObject.put("subArticles", jsonArray);
|
||||
}
|
||||
|
||||
payload.setBase64edData(Base64.getEncoder().encodeToString(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8)));
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user