Compare commits

...
184 Commits
Author SHA1 Message Date
imhao183 6d9eeb25d6 version 0.49->0.50 2020-12-10 18:28:27 +08:00
imhao183 32f63a7d9c 修改默认参数 2020-12-10 18:21:02 +08:00
imhao183 4d903ca379 1,添加设置群成员昵称api
2,配置当退群或者群踢人时,是否发送visible群通知
2020-12-10 18:03:41 +08:00
imhao183 d233dbdd99 添加禁止客户端发送某些类型配置功能 2020-12-02 15:38:16 +08:00
imhao183 0f32aa30ce 添加禁止客户端发送群通知开工 2020-12-02 15:32:46 +08:00
imndx 9e007185ba 解决sql语法错误. fix #305 2020-11-27 19:00:34 +08:00
imhao183 ab92bc116c update version to 0.49 2020-11-22 21:17:37 +08:00
imhao183 4308e51357 解决当用户关系不存在时,设置备注名失败的问题 2020-11-19 18:00:33 +08:00
imhao183 59977fb1ba 状态消息同步到发送者其它端时,排除掉发送端 2020-11-12 16:37:17 +08:00
imhao183 d912777974 fix file table name error 2020-11-12 10:28:32 +08:00
imhao183 19b7bc42ef fix build error 2020-11-11 18:34:43 +08:00
imhao183 e621bea8fa 添加撤回群发消息功能 2020-11-11 18:32:16 +08:00
imhao183 ca1cf03cc3 add recall multicast message request 2020-11-11 18:27:54 +08:00
imhao183 ed7e56ca75 add recall boardcast and multicast message api 2020-11-11 18:26:12 +08:00
heavyrain2012 40c5cd615d support java15 2020-11-11 16:29:59 +08:00
imhao183 3438de39ad 状态消息也需要同步到发送者的其它端 2020-11-11 13:08:28 +08:00
imhao183 7f6b2d93df toUsers参数没有带上及api兼容 2020-11-06 17:13:38 +08:00
imhao183 9c57a620c9 发送消息接口添加目标用户参数 2020-11-06 16:52:36 +08:00
imhao183 32252228b0 推送信息中带上用户Id 2020-11-06 16:44:44 +08:00
imhao183 396351cc15 update readme 2020-11-02 21:37:03 +08:00
imhao183 955c2182c8 update version to 0.48 2020-11-02 20:53:10 +08:00
heavyrain2012 823bd53da8 添加修正flyway migrate 38错误问题 2020-11-02 20:50:44 +08:00
heavyrain2012 e4588bfd9d 同步专业版数据库 2020-11-02 20:18:43 +08:00
imhao183 3b0f724ff0 update version to 0.47 2020-10-28 10:42:03 +08:00
imhao183 94bc595757 解决部分情况下消息id重复问题 2020-10-28 10:39:58 +08:00
imhao183 139042c8e7 添加免打扰功能及优化推送逻辑 2020-10-28 09:51:45 +08:00
imhao183 8e894e49b3 解决拉取历史消息问题 2020-10-23 11:24:44 +08:00
imhao183 c30a688032 remove useless fastjson 2020-10-22 10:37:12 +08:00
imhao183 06bcfea16e 拉取历史信息时,处理中间几个月时间没有消息的情况,最长间隔时24个月 2020-10-22 08:09:48 +08:00
imhao183 52bbf57760 Merge commit '30a62cfc58d12dc17406504873f1bc0e36f83a0d' into wildfirechat
* commit '30a62cfc58d12dc17406504873f1bc0e36f83a0d':
  Bump junit from 4.8.2 to 4.13.1 in /broker
2020-10-20 19:37:19 +08:00
imhao183 e63298f50b 实现群组/用户等信息变更通知 2020-10-19 09:09:53 +08:00
heavyrain2012 bc8baf3bcc 更新配置文件注释 2020-10-15 17:52:31 +08:00
dependabot[bot] 30a62cfc58 Bump junit from 4.8.2 to 4.13.1 in /broker
Bumps [junit](https://github.com/junit-team/junit4) from 4.8.2 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.8.2...r4.13.1)

Signed-off-by: dependabot[bot] <[email protected]>
2020-10-13 12:24:06 +00:00
imhao183 35b8133046 version 0.45 -> 0.46 2020-10-11 21:50:37 +08:00
imhao183 4a8500b99b 支持群主或管理员修改成员昵称 2020-10-11 21:23:45 +08:00
imhao183 c26e98b960 update proto 2020-10-11 21:19:13 +08:00
heavyrain2012 70fcc66672 添加默认文件传输助手用户 2020-10-06 12:14:22 +08:00
heavyrain2012 2538a6ca68 频道和机器人如果没有密钥,不允许使用api 2020-10-06 12:14:07 +08:00
heavyrain2012 6388f1b89c pc在线时,是否推送手机端信息定义修正 2020-10-05 22:49:02 +08:00
imhao183 ef1f25dab1 mute notification when pc online settings 2020-10-05 17:24:18 +08:00
imhao183 0a5c8a67bb 解决server api删除好友关系时不通知的问题 2020-09-28 09:45:38 +08:00
imhao183 ae3f0027ca 添加敏感词管理api测试代码 2020-09-20 08:40:22 +08:00
imhao183 76dedb3da7 添加server api发送好友请求功能 2020-09-15 09:05:42 +08:00
imhao183 580e9f80fb 重命名server api好友状态model 2020-09-15 09:05:34 +08:00
imhao183 63304c5c5f API获取用户好友列表按照时间排序 2020-09-14 22:47:45 +08:00
heavyrain2012 c377360049 version 0.44->0.45 2020-09-12 19:41:23 +08:00
imhao183 2e74a77e5b 优化用户关系的测试例 2020-09-10 18:47:14 +08:00
imhao183 90286e9484 解决server api无法删除好友问题 2020-09-10 18:46:43 +08:00
imhao183 7f479dd9e5 当A、B都向对方发出好友请求后,A接受好友邀请,A发送给B的好友邀请也要变成接受状态。
(cherry picked from commit a8d076a9ac7faa1a556caeaad239bb393824bd8b)
2020-09-03 15:37:22 +08:00
heavyrain2012 bae0805e64 创建用户时检查用户的有效性 2020-09-01 21:58:10 +08:00
imhao183 e5d63a8d5f 修正server api签名错误问题 2020-09-01 07:49:16 +08:00
imhao183 06fe70bd6f 兼容golang http请求 2020-08-29 09:42:29 +08:00
imhao183 5a14b2f2f0 兼容golang的http请求 2020-08-29 09:39:47 +08:00
imhao183 fbe5bf7a77 解决退出群组后成员获取群组成员错误问题 2020-08-27 18:20:07 +08:00
imhao183 4ae117dd6f update version 0.43 -> 0.44 2020-08-27 17:22:41 +08:00
imhao183 4518beff28 修改注释 2020-08-27 17:14:51 +08:00
imhao183 3cc278211b 修正客户端创建群组时,群主的成员状态错误问题 2020-08-25 21:04:53 +08:00
imhao183 355fc6cb06 接近server api设置好友关系时不通知客户端的问题 2020-08-25 15:07:32 +08:00
imhao183 aef125eb50 添加SDK对专业版群组禁言白名单的支持 2020-08-24 09:59:06 +08:00
imhao183 d89e641470 sdk 测试代码中区分社区版和专业版 2020-08-24 09:50:29 +08:00
imhao183 e41ae9a9e7 时间回拨问题优化 2020-08-24 09:30:59 +08:00
imhao183 989f5aa190 创建群组或者添加群组成员时,群组成员按照请求顺序排序 2020-08-20 12:09:52 +08:00
imhao183 a820300f04 用户在线状态通知中添加包名 2020-08-20 08:54:59 +08:00
imhao183 68707560b9 fix recall message content error 2020-08-18 22:37:16 +08:00
imhao183 bb5b6fac17 获取群成员列表时检查群成员权限 2020-08-12 14:58:28 +08:00
heavyrain2012 584eb094f3 修改注释 2020-08-08 17:16:34 +08:00
heavyrain2012 b9b1a76d71 添加撤回消息限制 2020-08-08 09:39:15 +08:00
heavyrain2012 a40950fb8c 更新注释 2020-08-08 08:18:23 +08:00
heavyrain2012 a6fe4e9d6e 修改server api 添加群组成员接口 2020-08-07 15:31:02 +08:00
heavyrain2012 6f06a499aa 修正添加群成员时,设置昵称不生效问题 2020-08-07 15:16:48 +08:00
imhao183 069770c411 version 0.42 -> 0.43 2020-08-01 18:54:55 +08:00
imhao183 1f5f7eb572 修正推送数据中unread message count不准确的问题 2020-08-01 09:25:24 +08:00
imhao183 405ad6c121 fix build error 2020-07-27 16:10:58 +08:00
imhao183 ff6e94cee7 remove useless errorcode 2020-07-22 11:53:15 +08:00
imhao183 db6f273cba fix build error 2020-07-21 22:13:11 +08:00
imhao183 df3bace44b 创建群组时添加更多的参数 2020-07-21 22:07:50 +08:00
heavyrain.lee 3f9a8be02c Update ISSUE_TEMPLATE.md 2020-07-17 12:03:42 +08:00
imhao183 39eb08e3f2 消息过期错误修改 2020-07-16 17:55:34 +08:00
imhao183 22a4ef4f42 修正撤回消息时异常信息问题 2020-07-16 15:22:21 +08:00
imhao183 da0d2e22cc message content add push attribute 2020-07-15 08:15:54 +08:00
imhao183 a80ef20da3 message content add push data attribute 2020-07-15 08:12:00 +08:00
imhao183 45fd11f641 修正黑名单问题 2020-07-13 21:21:37 +08:00
imhao183 cdc731a23b update 2020-07-10 11:34:32 +08:00
imhao183 68a968a94c 避免数据库表中的列名与某些数据库关键字冲突 2020-07-09 16:48:45 +08:00
imhao183 8604f4edf3 添加注释 2020-07-09 16:48:15 +08:00
imndx b1484b0c95 fix recall message issue 2020-07-06 16:02:11 +08:00
imhao183 631986f7a2 更新说明 2020-07-06 12:36:28 +08:00
imhao183 db27e77303 添加说明 2020-07-03 20:47:44 +08:00
imhao183 5177779066 fix server api group operation failure issue 2020-07-01 14:20:04 +08:00
imhao183 c4a764d81d update 2020-07-01 11:22:20 +08:00
imhao183 2c5ae2bd86 update version to 0.42 2020-07-01 11:04:42 +08:00
imhao183 b11d609ea0 update 2020-07-01 11:04:10 +08:00
imhao183 b8170c4757 修改好友欢迎提示方式,默认为关,需要在客户端上实现后打开 2020-06-30 17:15:53 +08:00
imhao183 e42d6f8e4f fix sql error 2020-06-25 16:07:49 +08:00
imhao183 e0c95bace9 数据库group表添加2个字段 2020-06-25 16:00:08 +08:00
imhao183 8623223991 添加群成员时,检查系统群最大成员数 2020-06-24 11:57:15 +08:00
heavyrain.lee efdcc24067 Update README.md 2020-06-24 09:26:46 +08:00
imhao183 ec18e40eb0 normal 类型的群组群成员可以修改群名称头像和extra,群主和群管理可以修改所有信息 2020-06-22 21:50:17 +08:00
heavyrain2012 f9d970c730 server api 发送接口添加extra字段 2020-06-18 17:22:45 +08:00
imhao183 590b02cc8e session修改成同步操作 2020-06-16 17:01:59 +08:00
imhao183 f2f75d3048 计数问题修正 2020-06-12 07:54:28 +08:00
imhao183 94466139f6 群成员增加加入时间字段 2020-06-11 20:58:24 +08:00
imhao183 70aeff9ac5 更新协议,在群成员数据结构中添加创建时间属性 2020-06-11 15:47:40 +08:00
imndx 7e56fe2ee0 参数校验 2020-06-09 17:11:48 +08:00
imndx 599547d627 修复黑名单问题. fix #213, fix #212 2020-06-09 16:53:24 +08:00
imhao183 28600ea7f9 修正文件名中带有&字符错误问题 2020-06-08 21:43:12 +08:00
heavyrain2012 a73507c673 解决群组通知line错误问题 2020-06-08 19:10:13 +08:00
imhao183 84b8d4cd09 fix build error 2020-06-04 07:47:11 +08:00
imhao183 b66aa3d634 消息转发时带上消息ID和时间戳 2020-06-04 07:44:11 +08:00
imhao183 508beaf62c SDK增加群内成员禁言功能 2020-05-24 19:02:39 +08:00
imhao183 e914afedf4 同步专业版数据库 2020-05-23 17:25:52 +08:00
heavyrain.lee 49c32d7fa1 Update README.md 2020-05-20 07:02:32 +08:00
imhao183 aac106d37e 更新注释 2020-05-15 09:51:31 +08:00
imhao183 8bd17a8093 更新注释 2020-05-13 19:16:15 +08:00
imhao183 b1f07f49ff api接口获取群成员信息时,过滤掉已删除成员 2020-05-11 12:12:51 +08:00
imhao183 86dddfd85f fix build error 2020-05-11 08:33:09 +08:00
imhao183 db733efc44 解决SDK中修改群信息的接口缺少自定义消息的问题 2020-05-06 21:00:41 +08:00
imhao183 69f28bd35b 当接受好友邀请时,如果已经是好友,返回“已经是好友”的错误码 2020-05-06 20:50:15 +08:00
heavyrain2012 4179788899 update version to 0.41 2020-05-05 19:29:03 +08:00
imhao183 1654baa523 添加服务器端删除消息的api 2020-05-03 13:38:18 +08:00
heavyrain2012 2163b9d580 remove useless code 2020-05-02 08:15:11 +08:00
heavyrain2012 8bec058e20 add ignore 2020-05-02 08:15:03 +08:00
imhao183 4aa2001f7b api 2020-05-01 12:39:40 +08:00
imhao183 c741b4e1da things api and db 2020-05-01 12:39:29 +08:00
imhao183 e771794bc0 things db config and sdk 2020-05-01 12:38:27 +08:00
imhao183 739452830d 用户退出时,多加一种选择,停用session不清除session 2020-04-28 07:40:55 +08:00
heavyrain.lee 16deebb565 添加是否禁止服务器端保存searchable_content字段的配置 2020-04-25 20:43:20 +08:00
heavyrain.lee 4411a75535 fix build error 2020-04-24 12:10:09 +08:00
heavyrain.lee 93bb9b50ae 添加PC下线功能 2020-04-24 12:08:17 +08:00
imhao183 1f45372b24 Revert "update"
This reverts commit 5ec14502f8.
2020-04-23 18:44:45 +08:00
imhao183 5ec14502f8 update 2020-04-22 08:05:36 +08:00
heavyrain.lee 7c0666e13c update sql 2020-04-18 20:38:36 +08:00
heavyrain.lee 42d0a5334e add sql 2020-04-18 20:28:37 +08:00
heavyrain.lee 8a4ae37247 update version to 0.40 2020-04-15 10:52:33 +08:00
heavyrain.lee c11b004e04 update 2020-04-15 10:34:33 +08:00
imhao183 4d07757b83 添加sticker/moments的bucket支持 2020-04-14 16:12:19 +08:00
heavyrain.lee bdc2f70785 update 2020-04-11 08:13:32 +08:00
imhao183 768fe75e04 update sdk to fix black list api 2020-04-08 16:13:21 +08:00
heavyrain.lee 2ba54a41db 撤回消息时带上被撤回消息的信息 2020-04-06 11:29:31 +08:00
imhao183 e414fa4a0a fix error 2020-04-05 22:48:28 +08:00
imhao183 da011f4957 添加PC在线状态通知开关 2020-04-05 21:14:39 +08:00
heavyrain.lee 38f42697cb upgrade mysql connector to 8.0.19 2020-04-05 12:11:56 +08:00
imhao183 3f5a8f579a 添加禁止好友请求的配置。另外更新部分配置说明 2020-04-04 10:11:42 +08:00
imhao183 5ebd77a1a1 添加禁止搜索用户和禁止昵称搜索用户的配置项 2020-04-04 09:55:53 +08:00
imhao183 1047db9990 add chatroom api 2020-04-02 22:50:04 +08:00
imhao183 83eae385b3 修改拒绝好友请求的错误 2020-04-02 18:26:15 +08:00
imhao183 e2a334af91 update version to 0.39 2020-03-29 13:38:29 +08:00
imhao183 7927cea105 敏感词过来所有消息的searchableContent字段 2020-03-27 17:00:31 +08:00
imhao183 029cdd5817 api添加好友时的推送通知 2020-03-27 16:42:25 +08:00
imhao183 54e868a36c linux平台的多端处理 2020-03-26 17:58:17 +08:00
imhao183 d099c2aa14 好友请求推送 2020-03-26 13:31:35 +08:00
heavyrain.lee 2f554bd046 获取用户状态接口 2020-03-25 10:25:18 +08:00
imhao183 310b2e1016 修正封禁用户登录返回的错误码错误 2020-03-24 16:42:04 +08:00
heavyrain.lee 117f5e6678 添加一个hz map 2020-03-19 09:53:47 +08:00
imhao183 49edf8e06d update 2020-03-12 12:55:34 +08:00
heavyrain.lee 93a56e4bbc fix friend extra action error 2020-03-09 18:12:53 +08:00
heavyrain.lee 4533c2aac6 添加获取聊天室成员API接口 2020-03-09 16:24:00 +08:00
heavyrain.lee 9cd3fe6b8c 客户端上报语言为空时,处理好友请求异常 2020-03-09 15:51:43 +08:00
imhao183 7e0f268b7c token expire time 2020-03-07 15:19:50 +08:00
heavyrain.lee c03a6f46fb 用户信息的extra 2020-03-07 11:27:39 +08:00
heavyrain.lee 7888c1e0d9 add extran in friendData 2020-03-07 10:34:33 +08:00
heavyrain.lee c0dd1c6581 add extra to friend table 2020-03-07 10:31:56 +08:00
heavyrain.lee 4f13cdeb76 update proto 2020-03-07 10:31:46 +08:00
heavyrain.lee a7aa42b851 修正用户信息中社交信息字段无法更新问题 2020-03-07 08:31:28 +08:00
heavyrain.lee 5187e63329 透传消息如果是超过一小时不在线就不需要发送了 2020-03-06 08:11:42 +08:00
heavyrain.lee 4b89774206 解决接收好友请求异常的错误 2020-03-02 16:51:46 +08:00
heavyrain.lee 46211aae44 修正存储消息是发送对象没有存储下来的错误 2020-03-02 15:53:06 +08:00
heavyrain.lee 3c241295ce 修正频道拉取远程消息的问题 2020-03-01 15:18:08 +08:00
heavyrain.lee e366962c65 修改定向消息拉取远程消息时的错误问题 2020-03-01 14:45:44 +08:00
heavyrain.lee a01fa84cae 调整用户关系API 2020-02-29 08:32:30 +08:00
heavyrain.lee a22f76d8d6 修改一个字段名 2020-02-28 19:16:20 +08:00
heavyrain.lee dd5ecd09f2 api的完善 2020-02-28 19:03:50 +08:00
heavyrain.lee 1bd060936c 机器人可以根据用户命或电话号码查询用户信息 2020-02-27 16:18:02 +08:00
imndx 0d03ef5758 文件接口允许跨域 2020-02-27 13:53:44 +08:00
heavyrain.lee 498bfccfe8 修正内置服务器上传文件链接错误 2020-02-26 12:45:33 +08:00
heavyrain.lee de064aa582 国际化支持 2020-02-25 15:49:43 +08:00
heavyrain.lee 54ce0d5b51 修改拒绝好友时的错误处理 2020-02-25 15:48:36 +08:00
heavyrain.lee b2e495b3ac 添加多语言处理 2020-02-25 15:48:29 +08:00
heavyrain.lee 603e8cf5fc 测试服务器存储文件名 2020-02-25 15:48:12 +08:00
imndx c3ae7cb0a7 fix handle friend request issue 2020-02-25 10:57:23 +08:00
heavyrain.lee a1b4eca6f2 修改推送时名称的问题 2020-02-21 11:19:52 +08:00
heavyrain.lee f65fe87119 好友通知消息支持英文 2020-02-21 09:23:44 +08:00
heavyrain.lee a4a9e1418e update 2020-02-20 16:08:45 +08:00
imhao183 5e92735e27 update 2020-02-20 16:08:45 +08:00
166 changed files with 6560 additions and 2717 deletions
+12 -8
View File
@@ -1,13 +1,17 @@
### Expected behavior
## 提issue小提示
为了尽快定位问题,需要提供足够的信息,请按照我们的要求格式来提问。***如果您不按照格式提问,我们将无法回复您的问题***
### Actual behavior
#### 操作说明
详细说明操作那个界面,每一步骤都要说得详细,如果是SDK或者api使用问题,需要详细说明调用的那个函数,参数都是什么。
### Steps to reproduce
#### 表现现象
描述一下什么现象,比如说函数返回error,errorcode是多少,或者界面上是什么状态,比如发送消息显示发送失败的红点。不要笼统的说功能有问题,不起作用。
### Minimal yet complete reproducer code (or URL to code) or complete log file
#### 预期结果
你认为正确的表现应该是什么样的。
### Moquette MQTT version
#### 补充条件
是否是毕现的,还是偶现的?是否只有在特殊的网络/设备/平台上出现,还是所有的都出现。还有您用的版本是什么时候的,是不是最新版
### JVM version (e.g. `java -version`)
### OS version (e.g. `uname -a`)
#### demo对比结果
请用demo对比测试,demo上是什么状态。
+3
View File
@@ -59,3 +59,6 @@ sdk/target
moments/target
monitor
wildfire_jmeter
git.properties
wildfirechat.license
broker/logs
+4 -10
View File
@@ -43,11 +43,6 @@
![野火IM](http://static.wildfirechat.cn/download_qrcode.png)
#### 加入野火官方体验交流群
使用野火IM移动客户端扫码下面二维码(不是使用微信扫码),和野火IM的爱好者一起畅谈野火IM的问题和经验:
![野火IM官方交流群](http://static.wildfirechat.cn/wildfirechat_official_group.jpeg)
#### 应用截图
![ios-demo](http://static.wildfirechat.cn/ios-demo.gif)
@@ -73,12 +68,11 @@
## 编译
在安装JDK1.8以上及maven的前提下,在命令行中执行```mvn clean compile package```,生成的目标文件在```./distribution/target/distribution-xxxx-bundle-tar.tar.gz```
> 由于使用了一个git的maven插件,如果本地没有git信息就会编译出错,请使用```git clone```的方法下载代码,或者下载压缩包解压后在根目录创建```.git```的空目录。建议用```git clone```的方式下载代码。
## 捐赠者名单
| 捐赠者 | 商标 | 金额 | 简介 |
| ----- | ---- | -------- | --- |
| [SAMOS](http://samos.io) | ![SAMOS](http://static.wildfirechat.cn/SAMOS.png) | 保密 | 一站式区块链解决方案服务商(http://samos.io) |
## 升级说明
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版本之外的版本不会出现此问题。
## 特别感谢
1. [moquette](https://github.com/moquette-io/moquette) 本项目是基于此项目二次开发而来,处理MQTT相关业务。
+27 -3
View File
@@ -61,6 +61,15 @@
</map-store>
</map>
<map name="user_friends_empty">
<time-to-live-seconds>86400</time-to-live-seconds>
<eviction-policy>LRU</eviction-policy>
<max-size policy="PER_NODE">1000000</max-size>
<eviction-percentage>10</eviction-percentage>
</map>
<set name="node_ids"/>
<multimap name="user_setting">
@@ -81,6 +90,12 @@
<map name="user_chatroom">
</map>
<multimap name="chatroom_black">
</multimap>
<multimap name="chatroom_manager">
</multimap>
<map name="robots">
<!-- 7 days -->
<time-to-live-seconds>604800</time-to-live-seconds>
@@ -92,14 +107,23 @@
<write-delay-seconds>0</write-delay-seconds>
</map-store>
</map>
<map name="things">
<map name="devices">
<!-- 7 days -->
<time-to-live-seconds>604800</time-to-live-seconds>
<eviction-policy>LRU</eviction-policy>
<max-size policy="PER_NODE">1000000</max-size>
<eviction-percentage>10</eviction-percentage>
<map-store enabled="true">
<class-name>io.moquette.persistence.DeviceLoader</class-name>
<write-delay-seconds>0</write-delay-seconds>
</map-store>
</map>
<multimap name="user_robots">
</multimap>
<multimap name="user_things">
<multimap name="user_devices">
</multimap>
<multimap name="chatroom_members">
+3
View File
@@ -0,0 +1,3 @@
#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
@@ -0,0 +1,2 @@
Above_Greeting_Message=This's the greeting
Friend_Can_Start_Chat=You're already friend, start chat now.
@@ -0,0 +1,2 @@
Above_Greeting_Message=This's the greeting
Friend_Can_Start_Chat=You're already friend, start chat now.
@@ -0,0 +1,2 @@
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
@@ -0,0 +1,2 @@
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
+91 -23
View File
@@ -52,10 +52,15 @@ client.proto.secret_key 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0
##用来生产im token的私钥,只在服务器使用,客户端不用。正式使用时为了安全一定要修改这个值,切记切记
token.key testim
##首次登录,是否接收之前的历史消息。0 不接收;1接收。
##token的过期时间,单位为毫秒,默认为无限期。如果需要设置无限期,客户端上一定需要加上token过期的处理。token过期的处理请参考文档的常见问题
##token.expire_time 2592000000
##首次登录,是否接收之前的历史消息。
##0 不接收历史消息,只接收5分钟以内的消息,由于服务器没有保存已经收取记录,所以如果有超过5分钟之前未收取的消息也不会收取下拉;
##1接收,会接收 message.max_queue 配置的条数的历史消息
message.roaming 0
##是否开启拉取远程历史消息
##是否开启拉取远程历史消息。如果为1,客户端在会话内如果本地消息读取完了,可以下拉继续加载在服务器上的该会话的消息;如果为0则不能。
message.remote_history_message 0
##服务器为每个用户缓存的消息数量。这个值改得太大,拉取消息时间变长,另外会占用大量内存。
@@ -64,10 +69,28 @@ message.max_queue 1024
##是否禁止陌生人聊天
message.disable_stranger_chat false
##黑名单处理策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃;
##黑名单策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃
message.blacklist.strategy 0
##是否禁止服务器端消息搜索,该功能暂未实现。目前的影响是如果打开,则存储消息时不单独保存_searchable_content字段
message.disable_remote_search false
##允许客户端撤回消息时限,单位是秒。群组管理员或群主撤回群成员消息、server api不受此限制,可以撤回任意时限内的消息
message.recall_time_limit 120
## 禁止客户端发送消息类型,消息类型以逗号分开,下面3个值为示例,可以删除。
## 一般用于重要类型消息,比如交易、充值等,禁止客户端发送,仅限于服务器发送,提高安全性。
message.forbidden_client_send_types 3999,4000,4001
##禁止搜索用户
friend.disable_search false
##禁止按照昵称搜索用户。
friend.disable_nick_name_search false
##禁止发送好友邀请,通过server api添加好友不受此限制
friend.disable_friend_request false
##好友请求重复发送的间隔,单位是毫秒,默认是7天,0为不限制
friend.repeat_request_duration 604800000
@@ -77,12 +100,25 @@ friend.reject_request_duration 2592000000
##好友请求过期时间,单位是毫秒,默认是7天,0为不限制
friend.request_expiration_duration 604800000
##添加好友后会发送欢迎消息,比如"你们已经是好友了,可以聊天了"。这个开关控制是用旧的方式还是用新的方式。
##旧的方式会发送notification消息(contenttype是80),内容会根据好友接收者的语言选择对应的语言,如果双方语言不一致会导致另外一方看到的不是本地语言。
##新的方式会发送添加好友消息(contenttype是93)和欢迎消息(contenttype是92),需要客户端实现这两种消息。
##如果客户端已经实现这两种消息可以打开这个开关
friend.new_welcome_message false
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000
## 用户向聊天室发送消息,自动加入聊天室
chatroom.rejoin_when_active true
## 是否允许客户端发送操作群的自定义群通知消息
group.allow_client_custom_operation_notification false
## 当群成员退出或者被移除时,是否同时给管理员和相关人员发送显式通知消息。
## 0 不发送,1 退群时发送,2 踢人时发送,3 退群和踢人时都发送。
group.visible_quit_or_kickoff_notification 0
#*********************************************************************
# hazelcase configuration
#*********************************************************************
@@ -91,7 +127,8 @@ hazelcast.configuration config/hazelcast.xml
#*********************************************************************
# Media server configuration
#*********************************************************************
##是否使用七牛云存储。1使用七牛;0使用内存文件服务器。
##是否使用七牛云存储。1使用七牛;0使用内存文件服务器。默认的七牛账户信息不可用,请在七牛官网申请账户并配置
## https://docs.wildfirechat.cn/server/media_server.html
media.server.use_qiniu 0
##媒体类型分类
@@ -117,6 +154,10 @@ qiniu.bucket_video_name media
qiniu.bucket_video_domain http://pghnpyzos.bkt.clouddn.com
qiniu.bucket_file_name media
qiniu.bucket_file_domain http://pghnpyzos.bkt.clouddn.com
qiniu.bucket_sticker_name media
qiniu.bucket_sticker_domain http://pghnpyzos.bkt.clouddn.com
qiniu.bucket_moments_name media
qiniu.bucket_moments_domain http://pghnpyzos.bkt.clouddn.com
qiniu.bucket_portrait_name storage
qiniu.bucket_portrait_domain http://cdn2.wildfirechat.cn
qiniu.bucket_favorite_name storage
@@ -127,41 +168,68 @@ qiniu.bucket_favorite_domain http://cdn2.wildfirechat.cn
# 本地媒体服务器配置。
local.media.storage.root media
# 是否支持多端登陆
# 是否支持多端登陆,为true时支持任意平台任意多个客户端同时登录;为false时每个平台只支持一个端登录,但不同平台可以同时登录。
server.multi_endpoint false
# 多平台连接状态通知(仅当multi_endpoint为false时有效),true时移动端可以收到pc或web端登录的通知。
server.multi_platform_notification false
#*********************************************************************
# Push server configuration
#*********************************************************************
##安卓推送服务器地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
push.android.server.address http://localhost:8085/android/push
##苹果推送服务器地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
push.ios.server.address http://localhost:8085/ios/push
#*********************************************************************
# User online status event callback
# 各种事件回调
#*********************************************************************
##用户在线状态事件回调地址
#user.online_status_callback http://localhost:8888/user/online_event
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#user.online_status_callback http://localhost:8888/im_event/user/online
#*********************************************************************
# MongoDB configuration
#*********************************************************************
#专业版支持,社区版请忽略
#mongodb.client_uri mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
#mongodb.client_uri mongodb://host1:27017,host2:27017,host3:27017/wfchat?replicaSet=myReplicaSet
mongodb.client_uri mongodb://wfc:123456@localhost:27017/wfchat
mongodb.database wfchat
mongodb.data_expire_days 1096
##用户信息变动事件回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#relation.relation_update_callback http://localhost:8888/im_event/user/relation
##用户信息变动事件回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#user.user_info_update_callback http://localhost:8888/im_event/user/info
##消息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.forward.url http://localhost:8888/im_event/message
##设备信息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#things_message.forward.url http://localhost:8888/im_event/things/message
##群组信息变动事件回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#group.group_info_update_callback http://localhost:8888/im_event/group/info
##群组信息变动事件回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#group.group_member_update_callback http://localhost:8888/im_event/group/member
##频道信息变动回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#channel.channel_info_update_callback http://localhost:8888/im_event/channel/info
##聊天室信息变动回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#chatroom.chatroom_info_update_callback http://localhost:8888/im_event/chatroom/info
##聊天室成员变动回调地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#chatroom.chatroom_member_update_callback http://localhost:8888/im_event/chatroom/member
#*********************************************************************
# Sensitive configuration
#*********************************************************************
##文本敏感词过滤处理方法,0 发送失败;1 发送成功但消息被服务器直接丢弃;2 命中的敏感词被替换成***;3 记录并继续发送
sensitive.filter.type 0
#*********************************************************************
# Message forward configuration
#*********************************************************************
##消息转发地址
#message.forward.url http://localhost:8087/message/forward
+1
View File
@@ -0,0 +1 @@
update t_channel set `_status` = 64 where `_status` = 3;
+2
View File
@@ -0,0 +1,2 @@
alter table t_messages add column `_to` varchar(64) DEFAULT NULL;
+1
View File
@@ -0,0 +1 @@
alter table t_friend add column `_extra` TEXT DEFAULT NULL;
@@ -0,0 +1,22 @@
DROP TABLE IF EXISTS `t_chatroom_blacklist`;
CREATE TABLE `t_chatroom_blacklist` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_cid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_state` tinyint NOT NULL DEFAULT 0,
`_expired_time` bigint(20) NOT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `cr_bl_uid_index` (`_cid`,_uid)
);
DROP TABLE IF EXISTS `t_chatroom_manager`;
CREATE TABLE `t_chatroom_manager` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_cid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_state` tinyint NOT NULL DEFAULT 0,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `cr_man_uid_index` (`_cid`,_uid)
);
+2
View File
@@ -0,0 +1,2 @@
alter table `t_user_messages` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages` ADD INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
+22
View File
@@ -0,0 +1,22 @@
DROP TABLE IF EXISTS `t_thing`;
DROP TABLE IF EXISTS `t_device`;
CREATE TABLE `t_device` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_token` varchar(64) DEFAULT '',
`_state` tinyint DEFAULT 0,
`_extra` TEXT DEFAULT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `device_uid_index` (`_uid` ASC)
);
DROP TABLE IF EXISTS `t_user_device`;
CREATE TABLE `t_user_device` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_did` varchar(64) DEFAULT '',
INDEX `user_device_uid_index` (`_uid` ASC),
INDEX `user_device_did_index` (`_did` ASC)
);
+1
View File
@@ -0,0 +1 @@
alter table t_user_session add column `_user_type` tinyint DEFAULT 0;
+42
View File
@@ -0,0 +1,42 @@
DROP TABLE IF EXISTS `t_read_report`;
CREATE TABLE `t_read_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NULL,
`_type` tinyint NULL,
`_line` int(11) NULL,
`_target` varchar(64) NULL,
`_dt` bigint(20) NOT NULL DEFAULT 0,
INDEX `read_report_index` (`_uid`, `_type`, `_line`, `_target`)
);
DROP TABLE IF EXISTS `t_user_read_report`;
CREATE TABLE `t_user_read_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_rid` int(11) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_seq` bigint(20) NOT NULL,
`_dt` DATETIME NOT NULL DEFAULT NOW(),
INDEX `user_read_report_index` (`_uid` DESC, `_seq` DESC),
UNIQUE INDEX `user_read_report_index2` (`_uid` DESC, `_rid` DESC)
);
DROP TABLE IF EXISTS `t_delivery_report`;
CREATE TABLE `t_delivery_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `delivery_index` (`_uid`)
);
DROP TABLE IF EXISTS `t_user_delivery_report`;
CREATE TABLE `t_user_delivery_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_rid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_seq` bigint(20) NOT NULL,
`_dt` DATETIME NOT NULL DEFAULT NOW(),
INDEX `user_delivery_index` (`_uid` DESC, `_seq` DESC),
UNIQUE INDEX `user_delivery_index2` (`_uid` DESC, `_rid` DESC)
);
+1
View File
@@ -0,0 +1 @@
alter table t_group_member add column `_create_dt` bigint(20) DEFAULT 0;
@@ -0,0 +1,2 @@
alter table `t_group` add column `_history_message` tinyint NOT NULL DEFAULT 0;
alter table `t_group` add column `_max_member_count` int(11) NOT NULL DEFAULT 2000;
+2
View File
@@ -0,0 +1,2 @@
alter table `t_settings` change column `value` `_value` varchar(64) NOT NULL;
alter table `t_settings` change column `desc` `_desc` varchar(64) NOT NULL;
+1
View File
@@ -0,0 +1 @@
alter table `t_group` modify column `_searchable` int(11) NOT NULL DEFAULT 0;
+15
View File
@@ -0,0 +1,15 @@
DROP TABLE IF EXISTS `t_file`;
CREATE TABLE `t_file` (
`_mid` bigint(20) NOT NULL PRIMARY KEY,
`_from` varchar(64) NOT NULL,
`_type` tinyint NOT NULL DEFAULT 0,
`_target` varchar(64) NOT NULL,
`_line` int(11) NOT NULL DEFAULT 0,
`_name` varchar(128) DEFAULT '',
`_url` varchar(1024) NOT NULL DEFAULT '',
`_size` int(11) NOT NULL DEFAULT 0,
`_download_count` int(11) DEFAULT 0,
`_dt` bigint(20) NOT NULL,
INDEX `file_conv_index` (`_type`, `_line`, `_target`, `_mid`),
INDEX `file_user_index` (`_from`, `_mid`)
);
+3
View File
@@ -0,0 +1,3 @@
insert into t_user (`_uid`,`_name`,`_display_name`,`_portrait`,`_type`,`_dt`) values ('wfc_file_transfer','wfc_file_transfer','文件传输助手','https://static.wildfirechat.cn/wfc_file_transfer.png',1,1);
insert into t_robot (`_uid`,`_owner`,`_secret`,`_callback`,`_state`,`_dt`) values ('wfc_file_transfer', 'wfc_file_transfer', '', '', 0, 1);
+1
View File
@@ -0,0 +1 @@
update t_channel set `_status` = 64 where `_status` = 3;
+38
View File
@@ -0,0 +1,38 @@
alter table t_messages add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_0 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_1 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_2 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_3 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_4 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_5 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_6 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_7 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_8 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_9 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_10 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_11 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_12 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_13 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_14 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_15 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_16 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_17 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_18 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_19 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_20 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_21 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_22 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_23 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_24 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_25 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_26 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_27 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_28 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_29 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_30 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_31 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_32 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_33 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_34 add column `_to` varchar(64) DEFAULT NULL;
alter table t_messages_35 add column `_to` varchar(64) DEFAULT NULL;
+1
View File
@@ -0,0 +1 @@
alter table t_friend add column `_extra` TEXT DEFAULT NULL;
@@ -0,0 +1,30 @@
DROP TABLE IF EXISTS `t_chatroom_blacklist`;
CREATE TABLE `t_chatroom_blacklist` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_cid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_state` tinyint NOT NULL DEFAULT 0,
`_expired_time` bigint(20) NOT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `cr_bl_uid_index` (`_cid`,_uid)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `t_chatroom_manager`;
CREATE TABLE `t_chatroom_manager` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_cid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_state` tinyint NOT NULL DEFAULT 0,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `cr_man_uid_index` (`_cid`,_uid)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
+260
View File
@@ -0,0 +1,260 @@
alter table `t_user_messages` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_0` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_1` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_2` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_3` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_4` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_5` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_6` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_7` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_8` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_9` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_10` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_11` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_12` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_13` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_14` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_15` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_16` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_17` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_18` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_19` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_20` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_21` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_22` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_23` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_24` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_25` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_26` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_27` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_28` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_29` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_30` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_31` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_32` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_33` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_34` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_35` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_36` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_37` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_38` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_39` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_40` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_41` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_42` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_43` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_44` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_45` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_46` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_47` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_48` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_49` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_50` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_51` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_52` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_53` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_54` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_55` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_56` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_57` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_58` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_59` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_60` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_61` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_62` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_63` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_64` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_65` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_66` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_67` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_68` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_69` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_70` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_71` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_72` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_73` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_74` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_75` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_76` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_77` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_78` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_79` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_80` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_81` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_82` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_83` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_84` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_85` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_86` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_87` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_88` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_89` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_90` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_91` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_92` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_93` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_94` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_95` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_96` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_97` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_98` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_99` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_100` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_101` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_102` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_103` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_104` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_105` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_106` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_107` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_108` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_109` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_110` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_111` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_112` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_113` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_114` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_115` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_116` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_117` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_118` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_119` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_120` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_121` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_122` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_123` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_124` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_125` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_126` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages_127` add column `_line` int(11) NOT NULL DEFAULT 0;
alter table `t_user_messages` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_0` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_1` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_2` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_3` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_4` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_5` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_6` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_7` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_8` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_9` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_10` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_11` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_12` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_13` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_14` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_15` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_16` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_17` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_18` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_19` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_20` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_21` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_22` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_23` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_24` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_25` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_26` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_27` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_28` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_29` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_30` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_31` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_32` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_33` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_34` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_35` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_36` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_37` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_38` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_39` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_40` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_41` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_42` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_43` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_44` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_45` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_46` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_47` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_48` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_49` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_50` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_51` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_52` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_53` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_54` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_55` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_56` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_57` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_58` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_59` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_60` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_61` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_62` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_63` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_64` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_65` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_66` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_67` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_68` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_69` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_70` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_71` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_72` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_73` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_74` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_75` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_76` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_77` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_78` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_79` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_80` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_81` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_82` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_83` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_84` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_85` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_86` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_87` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_88` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_89` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_90` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_91` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_92` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_93` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_94` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_95` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_96` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_97` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_98` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_99` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_100` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_101` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_102` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_103` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_104` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_105` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_106` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_107` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_108` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_109` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_110` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_111` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_112` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_113` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_114` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_115` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_116` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_117` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_118` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_119` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_120` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_121` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_122` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_123` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_124` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_125` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_126` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
alter table `t_user_messages_127` add INDEX `message_mid_line_uid_index` ( `_uid` DESC, `_line` DESC, `_mid` DESC );
+28
View File
@@ -0,0 +1,28 @@
DROP TABLE IF EXISTS `t_thing`;
DROP TABLE IF EXISTS `t_device`;
CREATE TABLE `t_device` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_token` varchar(64) DEFAULT '',
`_state` tinyint DEFAULT 0,
`_extra` TEXT DEFAULT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `device_uid_index` (`_uid` ASC)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `t_user_device`;
CREATE TABLE `t_user_device` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_did` varchar(64) DEFAULT '',
UNIQUE INDEX `user_device_uid_index` (`_uid` ASC, `_did` ASC),
INDEX `user_device_did_index` (`_did` ASC)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
+1
View File
@@ -0,0 +1 @@
alter table t_user_session add column `_user_type` tinyint DEFAULT 0 COMMENT "0, normal user; 1, robot; 2, device;";
+54
View File
@@ -0,0 +1,54 @@
DROP TABLE IF EXISTS `t_read_report`;
CREATE TABLE `t_read_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NULL,
`_type` tinyint NULL,
`_line` int(11) NULL,
`_target` varchar(64) NULL,
`_dt` bigint(20) NOT NULL DEFAULT 0,
INDEX `read_report_index` (`_uid`, `_type`, `_line`, `_target`)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `t_user_read_report`;
CREATE TABLE `t_user_read_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_rid` int(11) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_seq` bigint(20) NOT NULL,
`_dt` DATETIME NOT NULL DEFAULT NOW(),
INDEX `user_read_report_index` (`_uid` DESC, `_seq` DESC),
UNIQUE INDEX `user_read_report_index2` (`_uid` DESC, `_rid` DESC)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `t_delivery_report`;
CREATE TABLE `t_delivery_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_uid` varchar(64) NOT NULL,
`_dt` bigint(20) NOT NULL,
UNIQUE INDEX `delivery_index` (`_uid`)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `t_user_delivery_report`;
CREATE TABLE `t_user_delivery_report` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`_rid` varchar(64) NOT NULL,
`_uid` varchar(64) NOT NULL,
`_seq` bigint(20) NOT NULL,
`_dt` DATETIME NOT NULL DEFAULT NOW(),
INDEX `user_delivery_index` (`_uid` DESC, `_seq` DESC),
UNIQUE INDEX `user_delivery_index2` (`_uid` DESC, `_rid` DESC)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
+1
View File
@@ -0,0 +1 @@
alter table t_group_member add column `_create_dt` bigint(20) DEFAULT 0, COMMENT "group member create time";
@@ -0,0 +1,2 @@
alter table `t_group` add column `_history_message` tinyint NOT NULL DEFAULT 0, COMMENT "new group member can load group history messages";
alter table `t_group` add column `_max_member_count` int(11) NOT NULL DEFAULT 2000, COMMENT "max group member count";
+2
View File
@@ -0,0 +1,2 @@
alter table `t_settings` change column `value` `_value` varchar(64) NOT NULL;
alter table `t_settings` change column `desc` `_desc` varchar(64) NOT NULL;
@@ -0,0 +1 @@
alter table `t_group` modify column `_searchable` int(11) NOT NULL DEFAULT 0;
+18
View File
@@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `t_file`;
CREATE TABLE `t_file` (
`_mid` bigint(20) NOT NULL PRIMARY KEY,
`_from` varchar(64) NOT NULL,
`_type` tinyint NOT NULL DEFAULT 0,
`_target` varchar(64) NOT NULL,
`_line` int(11) NOT NULL DEFAULT 0,
`_name` varchar(128) DEFAULT '',
`_url` varchar(1024) NOT NULL DEFAULT '',
`_size` int(11) NOT NULL DEFAULT 0,
`_download_count` int(11) DEFAULT 0,
`_dt` bigint(20) NOT NULL,
INDEX `file_conv_index` (`_type`, `_line`, `_target`, `_mid`),
INDEX `file_user_index` (`_from`, `_mid`)
)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
+3
View File
@@ -0,0 +1,3 @@
insert into t_user (`_uid`,`_name`,`_display_name`,`_portrait`,`_type`,`_dt`) values ('wfc_file_transfer','wfc_file_transfer','文件传输助手','https://static.wildfirechat.cn/wfc_file_transfer.png',1,1);
insert into t_robot (`_uid`,`_owner`,`_secret`,`_callback`,`_state`,`_dt`) values ('wfc_file_transfer', 'wfc_file_transfer', '', '', 0, 1);
@@ -0,0 +1,6 @@
程序会自动创建数据库和执行migrate里的数据库,不需要手动创建库和执行sql语句。
数据库版本管理使用了flyway,flyway进行数据库升级时会校验数据库脚本的有效性,如果修改过这里的脚本,下次升级时就会失败。
强烈不建议修改数据库表结构,如果有内容(比如默认用户或者默认机器人的属性)需要修改,可以等数据库升级完成后,通过命令行或者数据库客户端进行修改。
由于服务具有缓存,一般修改过数据库内容后要重启后才能生效。
+3 -10
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.38</version>
<version>0.50</version>
</parent>
<artifactId>moquette-broker</artifactId>
@@ -48,7 +48,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<version>8.0.19</version>
</dependency>
<dependency>
@@ -132,7 +132,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
@@ -198,13 +198,6 @@
<version>2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
@@ -15,6 +15,7 @@ public class PushMessage {
public int convType;
public String target;
public String targetName;
public String userId;
public int line;
public int cntType;
public long serverTime;
@@ -23,6 +24,7 @@ public class PushMessage {
//推送类型,android推送分为小米/华为/魅族等。ios分别为开发和发布。
public int pushType;
public String pushContent;
public String pushData;
public int unReceivedMsg;
public int mentionedType;
public String packageName;
@@ -46,4 +48,13 @@ public class PushMessage {
this.isHiddenDetail = isHiddenDetail;
this.language = language;
}
public PushMessage(String sender, String target, long serverTime, String senderName, int unReceivedMsg, String language, int pushMessageType) {
this.sender = sender;
this.target = target;
this.senderName = senderName;
this.serverTime = serverTime;
this.unReceivedMsg = unReceivedMsg;
this.pushMessageType = pushMessageType;
this.language = language;
}
}
@@ -34,6 +34,7 @@ public class PushServer {
int PUSH_MESSAGE_TYPE_NORMAL = 0;
int PUSH_MESSAGE_TYPE_VOIP_INVITE = 1;
int PUSH_MESSAGE_TYPE_VOIP_BYE = 2;
int PUSH_MESSAGE_TYPE_FRIEND_REQUEST = 3;
}
private static PushServer INSTANCE = new PushServer();
@@ -57,7 +58,7 @@ public class PushServer {
}
public void pushMessage(PushMessage pushMessage, String deviceId, String pushContent) {
LOG.info("try to delivery push diviceId = {}, pushContent = {}", deviceId, pushContent);
LOG.info("try to delivery push diviceId = {}, conversationType = {}, pushContent = {}", deviceId, pushMessage.convType, pushContent);
executorService.execute(() ->{
try {
pushMessageInternel(pushMessage, deviceId, pushContent);
@@ -89,6 +90,7 @@ public class PushServer {
pushMessage.pushContent = pushContent;
pushMessage.deviceToken = session.getDeviceToken();
pushMessage.unReceivedMsg = badge;
pushMessage.userId = session.getUsername();
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS || session.getPlatform() == ProtoConstants.Platform.Platform_Android) {
String url = androidPushServerUrl;
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS) {
@@ -35,6 +35,7 @@ public class FileAction extends Action {
@Override
public boolean action(Request request, Response response) {
response.setHeader("Access-Control-Allow-Origin", "*");
if (false == Request.METHOD_GET.equalsIgnoreCase(request.getMethod())) {
response.sendError(HttpResponseStatus.METHOD_NOT_ALLOWED, "Please use GET method to request file!");
return true;
@@ -108,7 +109,8 @@ public class FileAction extends Action {
}
// 路径安全检查
if (httpPath.contains("/.") || httpPath.contains("./") || httpPath.charAt(0) == '.' || httpPath.charAt(httpPath.length() - 1) == '.' || ReUtil.isMatch(INSECURE_URI, httpPath)) {
String path = httpPath.substring(0, httpPath.lastIndexOf("/"));
if (path.contains("/.") || path.contains("./") || path.charAt(0) == '.' || path.charAt(path.length() - 1) == '.' || ReUtil.isMatch(INSECURE_URI, path)) {
return null;
}
@@ -254,7 +254,7 @@ public class UploadFileAction extends Action {
}
String filePath = dir + "/" + requestId;
String filePath = dir + "/" + (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
logger.info("the file path is " + filePath);
File tmpFile = new File(filePath);
@@ -279,7 +279,7 @@ public class UploadFileAction extends Action {
fileUpload.release();
response.setStatus(HttpResponseStatus.OK);
String relativePath = datePath + "/" + requestId;
String relativePath = datePath + "/" + (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
response.setContent("{\"key\":\"" + relativePath + "\"}");
break;
}
@@ -0,0 +1,87 @@
/*
* 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.InputAddFriendRequest;
import cn.wildfirechat.pojos.InputUpdateAlias;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.hazelcast.util.StringUtil;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import win.liyufan.im.IMTopic;
import java.util.concurrent.Executor;
@Route(APIPath.Friend_Send_Request)
@HttpMethod("POST")
public class AddFriendRequestAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputAddFriendRequest input = getRequestBody(request.getNettyRequest(), InputAddFriendRequest.class);
if (StringUtil.isNullOrEmpty(input.getUserId()) || StringUtil.isNullOrEmpty(input.getFriendUid())) {
sendResponse(response, ErrorCode.INVALID_PARAMETER, null);
return true;
}
WFCMessage.AddFriendRequest addFriendRequest = WFCMessage.AddFriendRequest.newBuilder().setReason(input.getReason()).setTargetUid(input.getFriendUid()).build();
RPCCenter.getInstance().sendRequest(input.getUserId(), null, IMTopic.AddFriendRequestTopic, addFriendRequest.toByteArray(), input.getUserId(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, null, null);
} else {
sendResponse(response, errorCode, null);
}
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, input.isForce());
return false;
}
return true;
}
}
@@ -44,9 +44,20 @@ abstract public class AdminAction extends Action {
if (!mLimitCounter.isGranted("admin")) {
return ErrorCode.ERROR_CODE_OVER_FREQUENCY;
}
String nonce = request.getHeader("nonce");
if (StringUtil.isNullOrEmpty(nonce)) {
nonce = request.getHeader("Nonce");
}
String timestamp = request.getHeader("timestamp");
if (StringUtil.isNullOrEmpty(timestamp)) {
timestamp = request.getHeader("Timestamp");
}
String sign = request.getHeader("sign");
if (StringUtil.isNullOrEmpty(sign)) {
sign = request.getHeader("Sign");
}
if (StringUtil.isNullOrEmpty(nonce) || StringUtil.isNullOrEmpty(timestamp) || StringUtil.isNullOrEmpty(sign)) {
return ErrorCode.INVALID_PARAMETER;
}
@@ -0,0 +1,88 @@
/*
* 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.InputBlacklistRequest;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import win.liyufan.im.IMTopic;
import java.util.concurrent.Executor;
@Route(APIPath.Blacklist_Update_Status)
@HttpMethod("POST")
public class BlacklistAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputBlacklistRequest inputData = getRequestBody(request.getNettyRequest(), InputBlacklistRequest.class);
if (inputData != null
&& !StringUtil.isNullOrEmpty(inputData.getUserId())
&& !StringUtil.isNullOrEmpty(inputData.getTargetUid())
) {
WFCMessage.BlackUserRequest friendRequest = WFCMessage.BlackUserRequest.newBuilder().setUid(inputData.getTargetUid()).setStatus(inputData.getStatus()).build();
RPCCenter.getInstance().sendRequest(inputData.getUserId(), null, IMTopic.BlackListUserTopic, friendRequest.toByteArray(), inputData.getUserId(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, null, null);
} else {
sendResponse(response, errorCode, null);
}
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> ctx.executor().execute(command);
}
}, true);
return false;
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.InputGetFriendList;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputStringList;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import com.xiaoleilu.loServer.model.FriendData;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Blacklist_Get_List)
@HttpMethod("POST")
public class BlacklistGetAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputUserId inputGetFriendList = getRequestBody(request.getNettyRequest(), InputUserId.class);
List<FriendData> dataList = messagesStore.getFriendList(inputGetFriendList.getUserId(), null, 0);
List<String> list = new ArrayList<>();
for (FriendData data : dataList) {
if (data.getBlacked() > 0) {
list.add(data.getFriendUid());
}
}
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.ok(new OutputStringList(list));
response.setContent(new Gson().toJson(result));
}
return true;
}
}
@@ -9,6 +9,10 @@
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.BroadMessageResult;
import cn.wildfirechat.pojos.OutputCheckUserOnline;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
@@ -16,10 +20,15 @@ import com.xiaoleilu.loServer.handler.Response;
import cn.wildfirechat.pojos.InputGetUserInfo;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import cn.wildfirechat.common.ErrorCode;
import java.util.concurrent.Executor;
@Route(APIPath.User_Get_Online_Status)
@HttpMethod("POST")
public class CheckUserOnlineAction extends AdminAction {
@@ -34,12 +43,34 @@ public class CheckUserOnlineAction extends AdminAction {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetUserInfo inputUserId = getRequestBody(request.getNettyRequest(), InputGetUserInfo.class);
if (inputUserId == null || !StringUtil.isNullOrEmpty(inputUserId.getUserId())) {
RPCCenter.getInstance().sendRequest(null, null, RPCCenter.CHECK_USER_ONLINE_REQUEST, inputUserId.getUserId().getBytes(), inputUserId.getUserId(), TargetEntry.Type.TARGET_TYPE_USER, null, true);
return true;
RPCCenter.getInstance().sendRequest(null, null, RPCCenter.CHECK_USER_ONLINE_REQUEST, inputUserId.getUserId().getBytes(), inputUserId.getUserId(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] res) {
OutputCheckUserOnline out = new Gson().fromJson(new String(res), OutputCheckUserOnline.class);
sendResponse(response, null, out);
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, true);
return false;
} else {
sendResponse(response, ErrorCode.INVALID_PARAMETER, null);
}
}
return true;
}
@@ -61,8 +61,8 @@ public class CreateChannelAction extends AdminAction {
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
byte[] data = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(data);
String secret = new String(data);
sendResponse(response, null, new OutputCreateChannel(inputCreateChannel.getTargetId(), secret));
String channelId = new String(data);
sendResponse(response, null, new OutputCreateChannel(channelId));
} else {
sendResponse(response, errorCode, null);
}
@@ -16,7 +16,7 @@ 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 cn.wildfirechat.pojos.InputFriendRequest;
import cn.wildfirechat.pojos.InputUpdateFriendStatusRequest;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
@@ -41,13 +41,16 @@ public class FriendRelationAction extends AdminAction {
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputFriendRequest friendAdd = getRequestBody(request.getNettyRequest(), InputFriendRequest.class);
InputUpdateFriendStatusRequest friendAdd = getRequestBody(request.getNettyRequest(), InputUpdateFriendStatusRequest.class);
if (friendAdd != null
&& !StringUtil.isNullOrEmpty(friendAdd.getUserId())
&& !StringUtil.isNullOrEmpty(friendAdd.getFriendUid())
) {
WFCMessage.HandleFriendRequest friendRequest = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(friendAdd.getFriendUid()).setStatus(friendAdd.getStatus()).build();
RPCCenter.getInstance().sendRequest(friendAdd.getUserId(), null, IMTopic.HandleFriendRequestTopic, friendRequest.toByteArray(), friendAdd.getFriendUid(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
WFCMessage.HandleFriendRequest.Builder friendRequestBuilder = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(friendAdd.getFriendUid()).setStatus(friendAdd.getStatus());
if (!StringUtil.isNullOrEmpty(friendAdd.getExtra())) {
friendRequestBuilder = friendRequestBuilder.setExtra(friendAdd.getExtra());
}
RPCCenter.getInstance().sendRequest(friendAdd.getUserId(), null, IMTopic.HandleFriendRequestTopic, friendRequestBuilder.build().toByteArray(), friendAdd.getFriendUid(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
@@ -9,6 +9,7 @@
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputStringList;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
@@ -22,6 +23,7 @@ import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@Route(APIPath.Friend_Get_List)
@@ -36,11 +38,12 @@ public class FriendRelationGetAction extends AdminAction {
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetFriendList inputGetFriendList = getRequestBody(request.getNettyRequest(), InputGetFriendList.class);
InputUserId inputGetFriendList = getRequestBody(request.getNettyRequest(), InputUserId.class);
List<FriendData> dataList = messagesStore.getFriendList(inputGetFriendList.getUserId(), null, 0);
List<String> list = new ArrayList<>();
dataList.sort(Comparator.comparingLong(FriendData::getTimestamp));
for (FriendData data : dataList) {
if (data.getState() == inputGetFriendList.getStatus()) {
if (data.getState() == 0) {
list.add(data.getFriendUid());
}
}
@@ -0,0 +1,74 @@
/*
* 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.OutputGetChatroomInfo;
import cn.wildfirechat.pojos.OutputStringList;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.UserClientEntry;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Route(APIPath.Chatroom_GetMembers)
@HttpMethod("POST")
public class GetChatroomMembersAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetChatroomInfo getChatroomInfo = getRequestBody(request.getNettyRequest(), InputGetChatroomInfo.class);
String chatroomid = getChatroomInfo.getChatroomId();
if (!StringUtil.isNullOrEmpty(chatroomid)) {
Collection<UserClientEntry> members = messagesStore.getChatroomMembers(chatroomid);
List<String> list = new ArrayList<>();
for (UserClientEntry entry : members) {
list.add(entry.userId);
}
RestResult result;
if (!list.isEmpty()) {
result = RestResult.ok(new OutputStringList(list));
} else {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
}
response.setStatus(HttpResponseStatus.OK);
response.setContent(new Gson().toJson(result));
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -14,6 +14,7 @@ import cn.wildfirechat.pojos.InputGetGroup;
import cn.wildfirechat.pojos.OutputGroupMemberList;
import cn.wildfirechat.pojos.PojoGroupInfo;
import cn.wildfirechat.pojos.PojoGroupMember;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
@@ -45,7 +46,7 @@ public class GetGroupMembersAction extends AdminAction {
&& (!StringUtil.isNullOrEmpty(inputGetGroup.getGroupId()))) {
List<WFCMessage.GroupMember> members = new ArrayList<>();
ErrorCode errorCode = messagesStore.getGroupMembers(inputGetGroup.getGroupId(), 0, members);
ErrorCode errorCode = messagesStore.getGroupMembers(null, inputGetGroup.getGroupId(), 0, members);
response.setStatus(HttpResponseStatus.OK);
@@ -56,6 +57,9 @@ public class GetGroupMembersAction extends AdminAction {
OutputGroupMemberList out = new OutputGroupMemberList();
out.setMembers(new ArrayList<>());
for (WFCMessage.GroupMember member : members) {
if (member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Removed) {
continue;
}
PojoGroupMember pm = new PojoGroupMember();
pm.setMember_id(member.getMemberId());
pm.setAlias(member.getAlias());
@@ -0,0 +1,85 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputKickoffGroupMember;
import cn.wildfirechat.pojos.InputSetGroupMemberAlias;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import win.liyufan.im.IMTopic;
import java.util.concurrent.Executor;
@Route(APIPath.Group_Set_Member_Alias)
@HttpMethod("POST")
public class ModifyGroupMemberAliasAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputSetGroupMemberAlias inputSetGroupMemberAlias = getRequestBody(request.getNettyRequest(), InputSetGroupMemberAlias.class);
if (inputSetGroupMemberAlias.isValide()) {
RPCCenter.getInstance().sendRequest(inputSetGroupMemberAlias.getOperator(), null, IMTopic.ModifyGroupMemberAliasTopic, inputSetGroupMemberAlias.toProtoGroupRequest().toByteArray(), inputSetGroupMemberAlias.getOperator(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, null, null);
} else {
sendResponse(response, errorCode, null);
}
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, true);
return false;
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -0,0 +1,84 @@
/*
* 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.RecallMessageData;
import cn.wildfirechat.pojos.RecallMultiCastMessageData;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import win.liyufan.im.IMTopic;
import java.util.concurrent.Executor;
@Route(APIPath.Msg_RecallMultiCast)
@HttpMethod("POST")
public class RecallMultiCastMessageAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
RecallMultiCastMessageData recallMessageData = getRequestBody(request.getNettyRequest(), RecallMultiCastMessageData.class);
if (recallMessageData != null && !StringUtil.isNullOrEmpty(recallMessageData.operator)) {
WFCMessage.RecallMultiCastMessageRequest recallRequest = WFCMessage.RecallMultiCastMessageRequest.newBuilder().setMessageId(recallMessageData.messageUid).addAllReceiver(recallMessageData.receivers).build();
RPCCenter.getInstance().sendRequest(recallMessageData.operator, null, IMTopic.RecallMultiCastMessageTopic, recallRequest.toByteArray(), recallMessageData.operator, TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
sendResponse(response, errorCode, null);
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, true);
return false;
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -34,9 +34,21 @@ abstract public class ChannelAction extends Action {
@Override
public ErrorCode preAction(Request request, Response response) {
String nonce = request.getHeader("nonce");
if (StringUtil.isNullOrEmpty(nonce)) {
nonce = request.getHeader("Nonce");
}
String timestamp = request.getHeader("timestamp");
if (StringUtil.isNullOrEmpty(timestamp)) {
timestamp = request.getHeader("Timestamp");
}
String sign = request.getHeader("sign");
if (StringUtil.isNullOrEmpty(sign)) {
sign = request.getHeader("Sign");
}
String cid = request.getHeader("cid");
if (StringUtil.isNullOrEmpty(cid)) {
cid = request.getHeader("Cid");
}
if (StringUtil.isNullOrEmpty(nonce) || StringUtil.isNullOrEmpty(timestamp) || StringUtil.isNullOrEmpty(sign) || StringUtil.isNullOrEmpty(cid)) {
return ErrorCode.INVALID_PARAMETER;
@@ -63,6 +75,10 @@ abstract public class ChannelAction extends Action {
if (channelInfo == null) {
return ErrorCode.INVALID_PARAMETER;
}
if (StringUtil.isNullOrEmpty(channelInfo.getSecret())) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
String str = nonce + "|" + channelInfo.getSecret() + "|" + timestamp;
String localSign = DigestUtils.sha1Hex(str);
@@ -38,9 +38,22 @@ abstract public class RobotAction extends Action {
@Override
public ErrorCode preAction(Request request, Response response) {
String nonce = request.getHeader("nonce");
if (StringUtil.isNullOrEmpty(nonce)) {
nonce = request.getHeader("Nonce");
}
String timestamp = request.getHeader("timestamp");
if (StringUtil.isNullOrEmpty(timestamp)) {
timestamp = request.getHeader("Timestamp");
}
String sign = request.getHeader("sign");
if (StringUtil.isNullOrEmpty(sign)) {
sign = request.getHeader("Sign");
}
String rid = request.getHeader("rid");
if (StringUtil.isNullOrEmpty(rid)) {
rid = request.getHeader("Rid");
}
if (StringUtil.isNullOrEmpty(nonce) || StringUtil.isNullOrEmpty(timestamp) || StringUtil.isNullOrEmpty(sign) || StringUtil.isNullOrEmpty(rid)) {
return ErrorCode.INVALID_PARAMETER;
}
@@ -67,6 +80,10 @@ abstract public class RobotAction extends Action {
return ErrorCode.ERROR_CODE_NOT_EXIST;
}
if (StringUtil.isNullOrEmpty(robot.getSecret())) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
String str = nonce + "|" + robot.getSecret() + "|" + timestamp;
String localSign = DigestUtils.sha1Hex(str);
return localSign.equals(sign) ? ErrorCode.ERROR_CODE_SUCCESS : ErrorCode.ERROR_CODE_AUTH_FAILURE;
@@ -113,7 +113,8 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
* @param response 响应对象
*/
private void doAction(ChannelHandlerContext ctx, Request request, Response response){
if( "/route".equalsIgnoreCase(request.getPath()) && "OPTIONS".equalsIgnoreCase(request.getMethod())){
if(("/route".equalsIgnoreCase(request.getPath()) || request.getPath().startsWith("/fs/"))
&& "OPTIONS".equalsIgnoreCase(request.getMethod())){
handleOptions(ctx, request, response);
return;
}
@@ -11,8 +11,6 @@ import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.activation.MimetypesFileTypeMap;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_RANGE;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
@@ -22,7 +20,6 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
public class HttpResponseHelper {
private static final Logger logger = LoggerFactory.getLogger(HttpResponseHelper.class);
private static final MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap();
/**
* sendResponse
@@ -149,7 +146,7 @@ public static String getContentType(String fileName) {
if (fileExtName.equals("png")) { // MimetypesFileTypeMap目前缺少png类型
return "image/png";
} else {
return mimetypesFileTypeMap.getContentType(fileName);
return "application/octet-stream";
}
}
@@ -14,15 +14,17 @@ public class FriendData implements Serializable {
private String userId;
private String friendUid;
private String alias;
private String extra;
private int state;
private int blacked;
private long timestamp;
public FriendData(String userId, String friendUid, String alias, int state, int blacked, long timestamp) {
public FriendData(String userId, String friendUid, String alias, String extra, int state, int blacked, long timestamp) {
this.userId = userId;
this.friendUid = friendUid;
this.alias = alias;
this.extra = extra;
this.state = state;
this.blacked = blacked;
this.timestamp = timestamp;
@@ -55,6 +57,14 @@ public class FriendData implements Serializable {
this.alias = alias;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
public int getState() {
return state;
}
@@ -77,6 +77,10 @@ public final class BrokerConstants {
public static final String QINIU_BUCKET_VIDEO_DOMAIN = "qiniu.bucket_video_domain";
public static final String QINIU_BUCKET_FILE_NAME= "qiniu.bucket_file_name";
public static final String QINIU_BUCKET_FILE_DOMAIN = "qiniu.bucket_file_domain";
public static final String QINIU_BUCKET_STICKER_NAME= "qiniu.bucket_sticker_name";
public static final String QINIU_BUCKET_STICKER_DOMAIN = "qiniu.bucket_sticker_domain";
public static final String QINIU_BUCKET_MOMENTS_NAME= "qiniu.bucket_moments_name";
public static final String QINIU_BUCKET_MOMENTS_DOMAIN = "qiniu.bucket_moments_domain";
public static final String QINIU_BUCKET_PORTRAIT_NAME= "qiniu.bucket_portrait_name";
public static final String QINIU_BUCKET_PORTRAIT_DOMAIN = "qiniu.bucket_portrait_domain";
public static final String QINIU_BUCKET_FAVORITE_NAME= "qiniu.bucket_favorite_name";
@@ -90,6 +94,17 @@ public final class BrokerConstants {
public static final String USER_ONLINE_STATUS_CALLBACK = "user.online_status_callback";
public static final String GROUP_INFO_UPDATE_CALLBACK = "group.group_info_update_callback";
public static final String GROUP_MEMBER_UPDATE_CALLBACK = "group.group_member_update_callback";
public static final String RELATION_UPDATE_CALLBACK = "relation.relation_update_callback";
public static final String USER_INFO_UPDATE_CALLBACK = "user.user_info_update_callback";
public static final String CHANNEL_INFO_UPDATE_CALLBACK = "channel.channel_info_update_callback";
public static final String CHATROOM_INFO_UPDATE_CALLBACK = "chatroom.chatroom_info_update_callback";
public static final String CHATROOM_MEMBER_UPDATE_CALLBACK = "chatroom.chatroom_member_update_callback";
public static final String HZ_Cluster_Node_External_IP = "node_external_ip";
public static final String HZ_Cluster_Node_External_Long_Port = "node_external_long_port";
public static final String HZ_Cluster_Node_External_Short_Port = "node_external_short_port";
@@ -99,6 +114,7 @@ public final class BrokerConstants {
public static final String CLIENT_PROTO_SECRET_KEY = "client.proto.secret_key";
public static final String TOKEN_SECRET_KEY = "token.key";
public static final String TOKEN_EXPIRE_TIME = "token.expire_time";
public static final String EMBED_DB_PROPERTY_NAME = "embed.db";
@@ -109,6 +125,7 @@ public final class BrokerConstants {
public static final String MESSAGE_Forward_Url = "message.forward.url";
public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint";
public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification";
public static final String MONGODB_Client_URI = "mongodb.client_uri";
public static final String MONGODB_Database = "mongodb.database";
@@ -122,13 +139,27 @@ public final class BrokerConstants {
public static final String MESSAGE_Disable_Stranger_Chat = "message.disable_stranger_chat";
public static final String MESSAGE_Blacklist_Strategy = "message.blacklist.strategy";
public static final String FRIEND_Disable_Search = "friend.disable_search";
public static final String FRIEND_Disable_NickName_Search = "friend.disable_nick_name_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 CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time";
public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active";
public static final String GROUP_Allow_Client_Custom_Operation_Notification = "group.allow_client_custom_operation_notification";
public static final String GROUP_Visible_Quit_Kickoff_Notification = "group.visible_quit_or_kickoff_notification";
public static final String MESSAGES_FORBIDDEN_CLIENT_SEND_TYPES = "message.forbidden_client_send_types";
public static final String MESSAGES_DISABLE_REMOTE_SEARCH = "message.disable_remote_search";
public static final String MESSAGES_RECALL_TIME_LIMIT = "message.recall_time_limit";
private BrokerConstants() {
}
@@ -23,11 +23,11 @@ public class AddFriendHandler extends GroupHandler<WFCMessage.AddFriendRequest>
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.AddFriendRequest request, Qos1PublishHandler.IMCallback callback) {
long[] head = new long[1];
ErrorCode errorCode = m_messagesStore.saveAddFriendRequest(fromUser, request, head);
ErrorCode errorCode = m_messagesStore.saveAddFriendRequest(fromUser, request, head, isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) {
WFCMessage.User user = m_messagesStore.getUserInfo(request.getTargetUid());
if (user != null && user.getType() == ProtoConstants.UserType.UserType_Normal) {
publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, request.getTargetUid(), head[0]);
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.internalRpcMsg(request.getTargetUid(), null, handleFriendRequest.toByteArray(), 0, fromUser, HandleFriendRequestTopic, false);
@@ -33,7 +33,13 @@ public class BroadcastMessageHandler extends IMHandler<WFCMessage.Message> {
}
long timestamp = System.currentTimeMillis();
long messageId = MessageShardingUtil.generateId();
long messageId = 0;
try {
messageId = MessageShardingUtil.generateId();
} catch (Exception e) {
e.printStackTrace();
return ErrorCode.ERROR_CODE_SERVER_ERROR;
}
message = message.toBuilder().setFromUser(fromUser).setMessageId(messageId).setServerTimestamp(timestamp).setConversation(WFCMessage.Conversation.newBuilder().setTarget(fromUser).setLine(message.getConversation().getLine()).setType(ProtoConstants.ConversationType.ConversationType_Private).build()).build();
long count = saveAndBroadcast(fromUser, clientID, message);
@@ -27,9 +27,15 @@ public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupReque
return ErrorCode.ERROR_CODE_GROUP_ALREADY_EXIST;
}
}
WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList());
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), isAdmin);
if (groupInfo != null) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(groupInfo.getTargetId(), fromUser, groupInfo.getName(), "").getCreateGroupNotifyContent();
@@ -29,8 +29,12 @@ public class DismissGroupHandler extends GroupHandler<WFCMessage.DismissGroupReq
} else if (isAdmin || (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted)
&& groupInfo.getOwner() != null && groupInfo.getOwner().equals(fromUser)) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
//send notify message first, then dismiss group
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(groupInfo.getTargetId(), fromUser, null, "").getDismissGroupNotifyContent();
@@ -30,6 +30,9 @@ public class FriendPullHandler extends IMHandler<WFCMessage.Version> {
if (!StringUtil.isNullOrEmpty(data.getAlias())) {
builder1.setAlias(data.getAlias());
}
if (!StringUtil.isNullOrEmpty(data.getExtra())) {
builder1.setExtra(data.getExtra());
}
builder.addEntry(builder1.build());
}
byte[] data = builder.build().toByteArray();
@@ -24,7 +24,7 @@ public class GetGroupMemberHandler extends IMHandler<WFCMessage.PullGroupMemberR
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.PullGroupMemberRequest request, Qos1PublishHandler.IMCallback callback) {
List<WFCMessage.GroupMember> members = new ArrayList<>();
ErrorCode errorCode = m_messagesStore.getGroupMembers(request.getTarget(), request.getHead(), members);
ErrorCode errorCode = m_messagesStore.getGroupMembers(fromUser, request.getTarget(), request.getHead(), members);
if (errorCode == ERROR_CODE_SUCCESS) {
WFCMessage.PullGroupMemberResult result = WFCMessage.PullGroupMemberResult.newBuilder().addAllMember(members).build();
@@ -60,6 +60,14 @@ public class GetMediaUploadTokenHandler extends IMHandler<WFCMessage.GetUploadTo
bucketName = MediaServerConfig.QINIU_BUCKET_FAVORITE_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_FAVORITE_DOMAIN;
break;
case 7:
bucketName = MediaServerConfig.QINIU_BUCKET_STICKER_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_STICKER_DOMAIN;
break;
case 8:
bucketName = MediaServerConfig.QINIU_BUCKET_MOMENTS_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_MOMENTS_DOMAIN;
break;
default:
bucketName = MediaServerConfig.QINIU_BUCKET_GENERAL_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_GENERAL_DOMAIN;
@@ -67,6 +67,14 @@ public class GetQiniuUploadTokenHandler extends IMHandler<Byte> {
bucketName = MediaServerConfig.QINIU_BUCKET_FAVORITE_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_FAVORITE_DOMAIN;
break;
case 7:
bucketName = MediaServerConfig.QINIU_BUCKET_STICKER_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_STICKER_DOMAIN;
break;
case 8:
bucketName = MediaServerConfig.QINIU_BUCKET_MOMENTS_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_MOMENTS_DOMAIN;
break;
default:
bucketName = MediaServerConfig.QINIU_BUCKET_GENERAL_NAME;
bucketDomain = MediaServerConfig.QINIU_BUCKET_GENERAL_DOMAIN;
@@ -13,12 +13,19 @@ import cn.wildfirechat.proto.WFCMessage;
import win.liyufan.im.MessageShardingUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
abstract public class GroupHandler<T> extends IMHandler<T> {
protected void sendGroupNotification(String fromUser, String targetId, List<Integer> lines, WFCMessage.MessageContent content) {
if (lines != null) {
sendGroupNotification(fromUser, targetId, lines, content, null);
}
protected void sendGroupNotification(String fromUser, String targetId, List<Integer> lines, WFCMessage.MessageContent content, Collection<String> toUsers) {
if (lines == null) {
lines = new ArrayList<>();
} else {
lines = new ArrayList<>(lines);
}
if (lines.isEmpty()) {
@@ -30,9 +37,16 @@ abstract public class GroupHandler<T> extends IMHandler<T> {
WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder().setContent(content).setServerTimestamp(timestamp);
builder.setConversation(builder.getConversationBuilder().setType(ProtoConstants.ConversationType.ConversationType_Group).setTarget(targetId).setLine(line));
builder.setFromUser(fromUser);
long messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(fromUser, null, builder.build(), false);
if(toUsers != null && !toUsers.isEmpty()) {
builder.addAllTo(toUsers);
}
try {
long messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(fromUser, null, builder.build(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -10,9 +10,12 @@ 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;
@@ -27,35 +30,59 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
long[] heads = new long[2];
ErrorCode errorCode = m_messagesStore.handleFriendRequest(fromUser, request, builder, heads, isAdmin);
if (errorCode == ERROR_CODE_SUCCESS && !isAdmin) {
long messageId = MessageShardingUtil.generateId();
long timestamp = System.currentTimeMillis();
builder.setMessageId(messageId);
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
if (errorCode == ERROR_CODE_SUCCESS) {
if (!isAdmin && builder.getConversation() != null && request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) {
try {
long messageId = MessageShardingUtil.generateId();
long timestamp = System.currentTimeMillis();
builder.setMessageId(messageId);
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder().setType(90).setContent("以上是打招呼信息");
builder = WFCMessage.Message.newBuilder();
builder.setFromUser(request.getTargetUid());
builder.setConversation(WFCMessage.Conversation.newBuilder().setTarget(fromUser).setLine(0).setType(ProtoConstants.ConversationType.ConversationType_Private).build());
builder.setContent(contentBuilder);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
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"));
}
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
builder = WFCMessage.Message.newBuilder();
builder.setFromUser(request.getTargetUid());
builder.setConversation(WFCMessage.Conversation.newBuilder().setTarget(fromUser).setLine(0).setType(ProtoConstants.ConversationType.ConversationType_Private).build());
builder.setContent(contentBuilder);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
contentBuilder.setContent("你们已经成为好友了,现在可以开始聊天了");
builder.setContent(contentBuilder);
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
publisher.publishNotification(IMTopic.NotifyFriendTopic, request.getTargetUid(), heads[0]);
publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]);
if (m_messagesStore.isNewFriendWelcomeMessage()) {
contentBuilder.setType(93);
} else {
contentBuilder.setContent(I18n.getString(language, "Friend_Can_Start_Chat"));
}
builder.setContent(contentBuilder);
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
if (request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted || isAdmin) {
publisher.publishNotification(IMTopic.NotifyFriendTopic, request.getTargetUid(), heads[0]);
publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]);
}
}
return errorCode;
}
@@ -32,10 +32,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_OVER_FREQUENCY;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
@@ -63,6 +62,9 @@ abstract public class IMHandler<T> {
protected static String actionName;
public static MessagesPublisher getPublisher() {
return publisher;
}
public IMHandler() {
try {
@@ -83,15 +85,11 @@ abstract public class IMHandler<T> {
}
}
for (Method method : getClass().getDeclaredMethods()
) {
if (method.getName() == actionName && method.getParameterCount() == 6 && !method.getParameterTypes()[4].equals(Object.class)) {
dataCls = method.getParameterTypes()[4];
break;
}
}
Type t = getClass().getGenericSuperclass();
ParameterizedType p = (ParameterizedType) t ;
Class<T> c = (Class<T>) p.getActualTypeArguments()[0];
dataCls = c;
if (dataCls.getSuperclass().equals(GeneratedMessage.class)) {
parseDataMethod = dataCls.getMethod("parseFrom", byte[].class);
} else if (dataCls.isPrimitive()) {
@@ -267,4 +265,13 @@ abstract public class IMHandler<T> {
mServer.getImBusinessScheduler().execute(() -> publisher.publish2Receivers(updatedMessage, notifyReceivers, clientID, ProtoConstants.PullType.Pull_Normal));
return notifyReceivers.size();
}
protected long publishRecallMultiCastMsg(long messageUid, List<String> receivers) {
WFCMessage.Message updatedMessage = m_messagesStore.getMessage(messageUid);
Set<String> notifyReceivers = new HashSet<>(receivers);
LOG.info("Multicast recall receiver count: {}", notifyReceivers.size());
mServer.getImBusinessScheduler().execute(() -> publisher.publish2Receivers(updatedMessage, notifyReceivers, null, ProtoConstants.PullType.Pull_Normal));
return notifyReceivers.size();
}
}
@@ -14,6 +14,9 @@ import cn.wildfirechat.pojos.GroupNotificationBinaryContent;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode;
import java.util.Set;
import static win.liyufan.im.IMTopic.KickoffGroupMemberTopic;
@Handler(value = KickoffGroupMemberTopic)
@@ -47,13 +50,24 @@ public class KickoffGroupMember extends GroupHandler<WFCMessage.RemoveGroupMembe
if (!isAllow && (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted)) {
errorCode = ErrorCode.ERROR_CODE_NOT_RIGHT;
} else {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
//send notify message first, then kickoff the member
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, request.getRemovedMemberList()).getKickokfMemberGroupNotifyContent();
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content);
}
if((m_messagesStore.getVisibleQuitKickoffNotification() & 0x02) > 0) {
Set<String> toUsers = m_messagesStore.getGroupManagers(request.getGroupId(), true);
toUsers.addAll(request.getRemovedMemberList());
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, request.getRemovedMemberList()).getKickokfMemberVisibleGroupNotifyContent();
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content, toUsers);
}
errorCode = m_messagesStore.kickoffGroupMembers(fromUser, isAdmin, request.getGroupId(), request.getRemovedMemberList());
}
}
@@ -0,0 +1,33 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package io.moquette.imhandler;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.GroupNotificationBinaryContent;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import com.hazelcast.util.StringUtil;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import static win.liyufan.im.IMTopic.KickoffGroupMemberTopic;
import static win.liyufan.im.IMTopic.KickoffPCClientTopic;
@Handler(value = KickoffPCClientTopic)
public class KickoffPCClientHandler extends GroupHandler<WFCMessage.IDBuf> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.IDBuf request, Qos1PublishHandler.IMCallback callback) {
String pcClientId = request.getId();
if (StringUtil.isNullOrEmpty(pcClientId)) {
return ErrorCode.INVALID_PARAMETER;
}
return m_sessionsStore.kickoffPCClient(fromUser, pcClientId);
}
}
@@ -32,6 +32,12 @@ public class LoadRemoteMessagesHandler extends IMHandler<WFCMessage.LoadRemoteMe
}
}
if (request.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Channel) {
if (!m_messagesStore.checkUserInChannel(fromUser, request.getConversation().getTarget())) {
return ErrorCode.ERROR_CODE_NOT_IN_CHANNEL;
}
}
WFCMessage.PullMessageResult result = m_messagesStore.loadRemoteMessages(fromUser, request.getConversation(), beforeUid, request.getCount());
byte[] data = result.toByteArray();
LOG.info("User {} load message with count({}), payload size({})", fromUser, result.getMessageCount(), data.length);
@@ -21,9 +21,13 @@ import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
public class ModifyGroupAliasHandler extends GroupHandler<WFCMessage.ModifyGroupMemberAlias> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.ModifyGroupMemberAlias request, Qos1PublishHandler.IMCallback callback) {
ErrorCode errorCode = m_messagesStore.modifyGroupAlias(fromUser, request.getGroupId(), request.getAlias());
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
ErrorCode errorCode = m_messagesStore.modifyGroupAlias(fromUser, request.getGroupId(), request.getAlias(), null, isAdmin);
if (errorCode == ERROR_CODE_SUCCESS && request.hasNotifyContent()) {
if (request.hasNotifyContent()&& request.getNotifyContent().getType() > 0) {
if (request.hasNotifyContent()&& request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, request.getAlias(), "").getModifyGroupMemberAliasNotifyContent();
@@ -22,9 +22,13 @@ import static win.liyufan.im.IMTopic.ModifyGroupInfoTopic;
public class ModifyGroupInfoHandler extends GroupHandler<WFCMessage.ModifyGroupInfoRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.ModifyGroupInfoRequest request, Qos1PublishHandler.IMCallback callback) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
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) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = null;
@@ -0,0 +1,39 @@
/*
* 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.pojos.GroupNotificationBinaryContent;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
@Handler(IMTopic.ModifyGroupMemberAliasTopic)
public class ModifyGroupMemberAliasHandler extends GroupHandler<WFCMessage.ModifyGroupMemberAlias> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.ModifyGroupMemberAlias request, Qos1PublishHandler.IMCallback callback) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
ErrorCode errorCode = m_messagesStore.modifyGroupAlias(fromUser, request.getGroupId(), request.getAlias(), request.getMemberId(), isAdmin);
if (errorCode == ERROR_CODE_SUCCESS && request.hasNotifyContent()) {
if (request.hasNotifyContent()&& request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, request.getAlias(), request.getMemberId()).getModifyGroupMemberAliasNotifyContent();
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content);
}
}
return errorCode;
}
}
@@ -36,7 +36,13 @@ public class MultiCastMessageHandler extends IMHandler<WFCMessage.MultiCastMessa
}
long timestamp = System.currentTimeMillis();
long messageId = MessageShardingUtil.generateId();
long messageId = 0;
try {
messageId = MessageShardingUtil.generateId();
} catch (Exception e) {
e.printStackTrace();
return ErrorCode.ERROR_CODE_SERVER_ERROR;
}
WFCMessage.Message message = WFCMessage.Message.newBuilder()
.setContent(multiCastMessage.getContent())
.setConversation(WFCMessage.Conversation.newBuilder().setTarget(fromUser).setType(ConversationType_Private).setLine(multiCastMessage.getLine()).build())
@@ -18,8 +18,7 @@ import win.liyufan.im.IMTopic;
public class PutUserSettingHandler extends IMHandler<WFCMessage.ModifyUserSettingReq> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.ModifyUserSettingReq request, Qos1PublishHandler.IMCallback callback) {
long timestamp = m_messagesStore.updateUserSettings(fromUser, request);
publisher.publishNotification(IMTopic.NotifyUserSettingTopic, fromUser, timestamp);
m_messagesStore.updateUserSettings(fromUser, request);
return ErrorCode.ERROR_CODE_SUCCESS;
}
}
@@ -14,20 +14,32 @@ import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode;
import java.util.Set;
import static win.liyufan.im.IMTopic.QuitGroupTopic;
@Handler(value = QuitGroupTopic)
public class QuitGroupHandler extends GroupHandler<WFCMessage.QuitGroupRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.QuitGroupRequest request, Qos1PublishHandler.IMCallback callback) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
ErrorCode errorCode = m_messagesStore.quitGroup(fromUser, request.getGroupId());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, "").getQuitGroupNotifyContent();
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content);
}
if((m_messagesStore.getVisibleQuitKickoffNotification() & 0x01) > 0) {
Set<String> toUsers = m_messagesStore.getGroupManagers(request.getGroupId(), true);
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, "").getQuitVisibleGroupNotifyContent();
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content, toUsers);
}
}
return errorCode;
}
@@ -21,13 +21,12 @@ import java.util.Set;
public class RecallMessageHandler extends IMHandler<WFCMessage.INT64Buf> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.INT64Buf int64Buf, Qos1PublishHandler.IMCallback callback) {
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, isAdmin);
ErrorCode errorCode = m_messagesStore.recallMessage(int64Buf.getId(), fromUser, clientID, isAdmin);
if(errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
return errorCode;
}
Set<String> notifyReceivers = new LinkedHashSet<>();
WFCMessage.Message message = m_messagesStore.getMessage(int64Buf.getId());
if (message == null) {
return ErrorCode.ERROR_CODE_NOT_EXIST;
@@ -35,11 +34,6 @@ public class RecallMessageHandler extends IMHandler<WFCMessage.INT64Buf> {
publish(fromUser, clientID, message);
//等待客户端实现根据撤回消息更新内容,之后可以删掉这段代码
m_messagesStore.getNotifyReceivers(fromUser, message.toBuilder(), notifyReceivers, false);
this.publisher.publishRecall2Receivers(int64Buf.getId(), fromUser, notifyReceivers, clientID);
return errorCode;
}
@@ -0,0 +1,36 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package io.moquette.imhandler;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic;
@Handler(value = IMTopic.RecallMultiCastMessageTopic)
public class RecallMultiCastMessageHandler extends IMHandler<WFCMessage.RecallMultiCastMessageRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.RecallMultiCastMessageRequest request, Qos1PublishHandler.IMCallback callback) {
if (!isAdmin) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
ErrorCode errorCode = m_messagesStore.recallCastMessage(request.getMessageId(), fromUser);
if(errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
return errorCode;
}
publishRecallMultiCastMsg(request.getMessageId(), request.getReceiverList());
return errorCode;
}
}
@@ -58,9 +58,14 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
boolean ignoreMsg = false;
if (!isAdmin) { //admin do not check the right
// 不能在端上直接发送撤回和群通知
if (message.getContent().getType() == 80 || (message.getContent().getType() >= 100 && message.getContent().getType() < 200)) {
if (message.getContent().getType() == 80 || message.getContent().getType() == 81 || (message.getContent().getType() >= 100 && message.getContent().getType() < 200)) {
return ErrorCode.INVALID_PARAMETER;
}
if(m_messagesStore.getClientForbiddenSendTypes().contains(message.getContent().getType())) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
int userStatus = m_messagesStore.getUserStatus(fromUser);
if (userStatus == ProtoConstants.UserStatus.Muted || userStatus == ProtoConstants.UserStatus.Forbidden) {
return ErrorCode.ERROR_CODE_FORBIDDEN_SEND_MSG;
@@ -100,7 +105,13 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
}
long timestamp = System.currentTimeMillis();
long messageId = MessageShardingUtil.generateId();
long messageId = 0;
try {
messageId = MessageShardingUtil.generateId();
} catch (Exception e) {
e.printStackTrace();
return ErrorCode.ERROR_CODE_SERVER_ERROR;
}
message = message.toBuilder().setFromUser(fromUser).setMessageId(messageId).setServerTimestamp(timestamp).build();
if (mForwardUrl != null) {
@@ -108,7 +119,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
}
if (!isAdmin && message.getContent().getType() == Text) {
if (!isAdmin) {
Set<String> matched = m_messagesStore.handleSensitiveWord(message.getContent().getSearchableContent());
if (matched != null && !matched.isEmpty()) {
m_messagesStore.storeSensitiveMessage(message);
@@ -21,9 +21,13 @@ import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
public class SetGroupManagerHandler extends GroupHandler<WFCMessage.SetGroupManagerRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.SetGroupManagerRequest request, Qos1PublishHandler.IMCallback callback) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
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) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, request.getType() + "", request.getUserIdList()).getSetGroupManagerNotifyContent();
@@ -21,9 +21,13 @@ import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
public class TransferGroupHandler extends GroupHandler<WFCMessage.TransferGroupRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.TransferGroupRequest request, Qos1PublishHandler.IMCallback callback) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && !isAdmin && !m_messagesStore.isAllowClientCustomGroupNotification()) {
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) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0 && (isAdmin || m_messagesStore.isAllowClientCustomGroupNotification())) {
sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent());
} else {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, request.getNewOwner()).getTransferGroupNotifyContent();
@@ -33,13 +33,16 @@ import java.util.function.Function;
import static cn.wildfirechat.proto.ProtoConstants.PersistFlag.Transparent;
import static io.moquette.persistence.MemoryMessagesStore.USER_STATUS;
import static io.moquette.server.Constants.MAX_MESSAGE_QUEUE;
import static cn.wildfirechat.proto.ProtoConstants.SearchUserType.*;
public class DatabaseStore {
private static final Logger LOG = LoggerFactory.getLogger(DatabaseStore.class);
private final ThreadPoolExecutorWrapper mScheduler;
private boolean disableRemoteMessageSearch = false;
public void setDisableRemoteMessageSearch(boolean disableRemoteMessageSearch) {
this.disableRemoteMessageSearch = disableRemoteMessageSearch;
}
public DatabaseStore(ThreadPoolExecutorWrapper scheduler) {
this.mScheduler = scheduler;
@@ -83,10 +86,10 @@ public class DatabaseStore {
try {
connection = DBUtil.getConnection();
String sql = "insert into t_settings " +
" (`id`, `value`, `desc`) values(?, ?, ?)" +
" (`id`, `_value`, `_desc`) values(?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`value` = ?," +
"`desc` = ?";
"`_value` = ?," +
"`_desc` = ?";
statement = connection.prepareStatement(sql);
@@ -117,7 +120,7 @@ public class DatabaseStore {
try {
connection = DBUtil.getConnection();
String sql = "select `value`, `desc` from t_settings where `id` = ?";
String sql = "select `_value`, `_desc` from t_settings where `id` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
@@ -200,10 +203,9 @@ public class DatabaseStore {
}
if (page > 0) {
sql += "offset = '" + page * 20 + "'";
sql += " offset " + page * 20;
}
statement = connection.prepareStatement(sql);
int index = 1;
@@ -328,7 +330,7 @@ public class DatabaseStore {
String sql = "select `_mid`" +
", `_alias`" +
", `_type`" +
", `_dt` from t_group_member where _gid = ?";
", `_dt`, `_create_dt` from t_group_member where _gid = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, groupId);
@@ -355,6 +357,9 @@ public class DatabaseStore {
long longValue = rs.getLong(index++);
builder.setUpdateDt(longValue);
longValue = rs.getLong(index++);
builder.setCreateDt(longValue);
WFCMessage.GroupMember member = builder.build();
groupMembers.put(groupId, member);
}
@@ -380,7 +385,7 @@ public class DatabaseStore {
try {
connection = DBUtil.getConnection();
String sql = "select `_uid`, `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt` from t_friend";
String sql = "select `_uid`, `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt`, `_extra` from t_friend";
statement = connection.prepareStatement(sql);
int index;
@@ -411,6 +416,8 @@ public class DatabaseStore {
long longvalue = rs.getLong(index++);
builder.setTimestamp(longvalue);
builder.setExtra(rs.getString(index++));
friendsMap.put(builder.getUserId(), builder);
}
} catch (SQLException e) {
@@ -492,13 +499,24 @@ public class DatabaseStore {
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "insert into " + MessageShardingUtil.getMessageTable(message.getMessageId()) +
" (`_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_searchable_key`, `_dt`, `_content_type`) values(?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_data` = ?," +
"`_searchable_key` = ?," +
"`_dt` = ?," +
"`_content_type` = ?";
String table = MessageShardingUtil.getMessageTable(message.getMessageId());
String sql;
if (disableRemoteMessageSearch) {
sql = "insert into " + table +
" (`_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_dt`, `_content_type`, `_to`) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_data` = ?," +
"`_dt` = ?," +
"`_content_type` = ?";
} else {
sql = "insert into " + table +
" (`_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_searchable_key`, `_dt`, `_content_type`, `_to`) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_data` = ?," +
"`_searchable_key` = ?," +
"`_dt` = ?," +
"`_content_type` = ?";
}
String searchableContent = message.getContent().getSearchableContent() == null ? "" : message.getContent().getSearchableContent();
@@ -512,12 +530,23 @@ public class DatabaseStore {
Blob blob = connection.createBlob();
blob.setBytes(1, message.getContent().toByteArray());
statement.setBlob(index++, blob);
statement.setString(index++, searchableContent);
if (!disableRemoteMessageSearch) {
statement.setString(index++, searchableContent);
}
statement.setTimestamp(index++, new Timestamp(message.getServerTimestamp()));
statement.setInt(index++, message.getContent().getType());
String to = message.getToUser();
if (StringUtil.isNullOrEmpty(message.getToUser())) {
if (message.getToList()!= null && message.getToList().size() == 1) {
to = message.getToList().get(0);
}
}
statement.setString(index++, to);
statement.setBlob(index++, blob);
statement.setString(index++, searchableContent);
if (!disableRemoteMessageSearch) {
statement.setString(index++, searchableContent);
}
statement.setTimestamp(index++, new Timestamp(message.getServerTimestamp()));
statement.setInt(index++, message.getContent().getType());
@@ -721,21 +750,35 @@ public class DatabaseStore {
}
List<WFCMessage.Message> loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count) {
List<WFCMessage.Message> messages = loadRemoteMessagesFromTable(user, conversation, beforeUid, count, MessageShardingUtil.getMessageTable(beforeUid));
if (messages != null && messages.size() < count) {
String nexTable = MessageShardingUtil.getPreviousMessageTable(beforeUid);
if (!StringUtil.isNullOrEmpty(nexTable)) {
List<WFCMessage.Message> nextMessages = loadRemoteMessagesFromTable(user, conversation, beforeUid, count - messages.size(), nexTable);
if (nextMessages != null) {
messages.addAll(nextMessages);
}
List<WFCMessage.Message> messages = new ArrayList<>();
long[] before = new long[1];
before[0] = beforeUid;
boolean hasMore = loadRemoteMessagesFromTable(user, conversation, before, count, MessageShardingUtil.getMessageTable(beforeUid), messages);
while (messages.size() < count && hasMore) {
hasMore = loadRemoteMessagesFromTable(user, conversation, before, count - messages.size(), MessageShardingUtil.getMessageTable(beforeUid), messages);
}
int month = 0;
while (messages.size() < count && !DBUtil.IsEmbedDB && month++ < 24) {
String nexTable = MessageShardingUtil.getMessageTable(beforeUid, -month);
int size = messages.size();
hasMore = true;
while (size == messages.size() && hasMore) {
hasMore = loadRemoteMessagesFromTable(user, conversation, before, count - messages.size(), nexTable, messages);
}
if (size < messages.size()) {
break;
}
}
return messages;
}
List<WFCMessage.Message> loadRemoteMessagesFromTable(String user, WFCMessage.Conversation conversation, long beforeUid, int count, String table) {
String sql = "select `_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_dt` from " + table +" where";
boolean loadRemoteMessagesFromTable(String user, WFCMessage.Conversation conversation, long[] before, int count, String table, List<WFCMessage.Message> messages) {
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 = ?))";
} else {
@@ -747,7 +790,6 @@ public class DatabaseStore {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
List<WFCMessage.Message> out = new ArrayList<>();
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
@@ -764,9 +806,12 @@ public class DatabaseStore {
statement.setInt(index++, count);
resultSet = statement.executeQuery();
while (resultSet.next()) {
count--;
WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
index = 1;
builder.setMessageId(resultSet.getLong(index++));
before[0] = builder.getMessageId();
builder.setFromUser(resultSet.getString(index++));
WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
cb.setType(resultSet.getInt(index++));
@@ -777,9 +822,31 @@ public class DatabaseStore {
WFCMessage.MessageContent messageContent = WFCMessage.MessageContent.parseFrom(blob.getBinaryStream());
builder.setContent(messageContent);
builder.setServerTimestamp(resultSet.getTimestamp(index++).getTime());
String to = resultSet.getString(index++);
if (!StringUtil.isNullOrEmpty(to)) {
if (to.equals(user) || builder.getFromUser().equals(user)) {
builder.setToUser(to);
} else {
continue;
}
}
WFCMessage.Message message = builder.build();
out.add(message);
boolean expired = false;
if (message.getContent().getExpireDuration() > 0) {
if (System.currentTimeMillis() > message.getServerTimestamp() + message.getContent().getExpireDuration()*1000) {
expired = true;
}
}
if (!expired) {
messages.add(message);
}
}
if (count == 0) {
return true;
}
} catch (SQLException | IOException e) {
e.printStackTrace();
@@ -787,7 +854,7 @@ public class DatabaseStore {
} finally {
DBUtil.closeDB(connection, statement, resultSet);
}
return out;
return false;
}
void persistUserMessage(final String userId, final long messageId, final long messageSeq) {
@@ -991,6 +1058,10 @@ public class DatabaseStore {
out.add(builder.build());
}
if (out.isEmpty()) {
WFCMessage.UserSettingEntry.Builder builder = WFCMessage.UserSettingEntry.newBuilder().setScope(999).setKey("").setValue("").setUpdateDt(0);
out.add(builder.build());
}
return out;
} catch (SQLException e) {
// TODO Auto-generated catch block
@@ -1290,7 +1361,6 @@ public class DatabaseStore {
}
void updateSessionDeleted(String uid, String cid, int deleted) {
mScheduler.execute(()->{
Connection connection = null;
PreparedStatement statement = null;
@@ -1315,11 +1385,9 @@ public class DatabaseStore {
} finally {
DBUtil.closeDB(connection, statement);
}
});
}
void updateSessionPlatform(String uid, String cid, int platform) {
mScheduler.execute(()->{
Connection connection = null;
PreparedStatement statement = null;
@@ -1344,7 +1412,6 @@ public class DatabaseStore {
} finally {
DBUtil.closeDB(connection, statement);
}
});
}
private boolean strEqual(String left, String right) {
@@ -1446,8 +1513,9 @@ public class DatabaseStore {
try {
connection = DBUtil.getConnection();
String sql;
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX
|| platform == ProtoConstants.Platform.Platform_iOS || platform == ProtoConstants.Platform.Platform_Android) {
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX) {
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";
@@ -1463,9 +1531,10 @@ public class DatabaseStore {
statement.setString(index++, uid);
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX) {
if (platform == ProtoConstants.Platform.Platform_Windows || platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_LINUX) {
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_iOS);
statement.setInt(index++, ProtoConstants.Platform.Platform_Android);
@@ -1602,7 +1671,7 @@ public class DatabaseStore {
", `_mid`" +
", `_alias`" +
", `_type`" +
", `_dt`) values(?, ?, ?, ?, ?)" +
", `_dt`, `_create_dt`) values(?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_alias` = ?," +
"`_type` = ?," +
@@ -1623,6 +1692,7 @@ public class DatabaseStore {
statement.setString(index++, member.getAlias());
statement.setInt(index++, member.getType());
statement.setLong(index++, dt);
statement.setLong(index++, member.getCreateDt());
statement.setString(index++, member.getAlias());
statement.setInt(index++, member.getType());
statement.setLong(index++, dt);
@@ -2127,6 +2197,33 @@ public class DatabaseStore {
}
});
}
boolean isUidAndNameConflict(String uid, String name) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
long start = System.currentTimeMillis();
try {
connection = DBUtil.getConnection();
String sql = "select _uid from t_user where _name = ? and _uid <> ? limit 1";
statement = connection.prepareStatement(sql);
statement.setString(1, name);
statement.setString(2, uid);
rs = statement.executeQuery();
if (rs.next()) {
String conflictId = rs.getString(1);
LOG.error("user {} already have name {} !!!", conflictId, name);
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return false;
}
void updateUser(final WFCMessage.User user) throws Exception {
LOG.info("Database update user info {} {}", user.getUid(), user.getUpdateDt());
@@ -2473,7 +2570,7 @@ public class DatabaseStore {
ResultSet rs = null;
try {
connection = DBUtil.getConnection();
String sql = "select `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt` from t_friend where `_uid` = ?";
String sql = "select `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt`, `_extra` from t_friend where `_uid` = ?";
statement = connection.prepareStatement(sql);
@@ -2489,8 +2586,9 @@ public class DatabaseStore {
int state = rs.getInt(3);
int blacked = rs.getInt(4);
long timestamp = rs.getLong(5);
String extra = rs.getString(6);
FriendData data = new FriendData(userId, uid, alias, state, blacked, timestamp);
FriendData data = new FriendData(userId, uid, alias, extra, state, blacked, timestamp);
out.add(data);
}
return out;
@@ -2510,7 +2608,7 @@ public class DatabaseStore {
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "update t_friend set `_alias` = '', `_state` = 1, `_blacked` = 0, `_dt` = ? where `_uid` = ? or `_friend_uid` = ?";
String sql = "update t_friend set `_alias` = '', `_state` = 1, `_blacked` = 0, `_dt` = ?, `_extra` = 0 where `_uid` = ? or `_friend_uid` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
@@ -2693,12 +2791,13 @@ public class DatabaseStore {
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "insert into t_friend (`_uid`, `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt`) values(?, ?, ?, ?, ?, ?)" +
String sql = "insert into t_friend (`_uid`, `_friend_uid`, `_alias`, `_state`, `_blacked`, `_dt`, `_extra`) values(?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_alias` = ?," +
"`_state` = ?," +
"`_blacked` = ?," +
"`_dt` = ?";
"`_dt` = ?," +
"`_extra` = ?";
statement = connection.prepareStatement(sql);
@@ -2709,10 +2808,12 @@ public class DatabaseStore {
statement.setInt(index++, request.getState());
statement.setInt(index++, request.getBlacked());
statement.setLong(index++, request.getTimestamp());
statement.setString(index++, request.getExtra());
statement.setString(index++, request.getAlias());
statement.setInt(index++, request.getState());
statement.setInt(index++, request.getBlacked());
statement.setLong(index++, request.getTimestamp());
statement.setString(index++, request.getExtra());
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
@@ -3001,7 +3102,7 @@ public class DatabaseStore {
rs = statement.executeQuery();
while (rs.next()) {
String value = rs.getString(index++);
String value = rs.getString(1);
if (!StringUtil.isNullOrEmpty(value)) {
out.add(value);
}
@@ -3044,10 +3145,9 @@ public class DatabaseStore {
if (page > 0) {
sql += "offset = '" + page * 20 + "'";
sql += " offset " + page * 20;
}
statement = connection.prepareStatement(sql);
int index = 1;
if (buzzy) {
File diff suppressed because it is too large Load Diff
@@ -279,6 +279,9 @@ public class MemorySessionStore implements ISessionsStore {
@Override
public Session getSession(String clientID) {
if (StringUtil.isNullOrEmpty(clientID)) {
return null;
}
Session session = sessions.get(clientID);
if (session == null) {
LOG.error("Can't find the session for client <{}>", clientID);
@@ -378,8 +381,8 @@ public class MemorySessionStore implements ISessionsStore {
if (s.getPlatform() == ProtoConstants.Platform.Platform_Android || s.getPlatform() == ProtoConstants.Platform.Platform_iOS) {
remove = true;
}
} else if(platform == ProtoConstants.Platform.Platform_OSX || platform == ProtoConstants.Platform.Platform_Windows) {
if (s.getPlatform() == ProtoConstants.Platform.Platform_OSX || s.getPlatform() == ProtoConstants.Platform.Platform_Windows) {
} 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) {
remove = true;
}
} else {
@@ -650,6 +653,37 @@ public class MemorySessionStore implements ISessionsStore {
return sessions.get(clientID).secondPhaseStore.size();
}
@Override
public ErrorCode kickoffPCClient(String operator, String pcClientId) {
Session session = sessions.get(pcClientId);
if (session != null) {
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) {
databaseStore.updateSessionDeleted(operator, pcClientId, 1);
sessions.remove(pcClientId);
mServer.getProcessor().kickoffSession(session);
} else {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
return ErrorCode.ERROR_CODE_SUCCESS;
}
@Override
public void disableSession(String clientId) {
Session session = sessions.get(clientId);
if (session != null && session.getDeleted() == 0) {
databaseStore.updateSessionDeleted(session.getUsername(), clientId, 1);
ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(session.username);
sessionSet.remove(clientId);
sessions.remove(clientId);
}
}
@Override
public void cleanSession(String clientID) {
LOG.info("Fooooooooo <{}>", clientID);
@@ -677,4 +711,8 @@ public class MemorySessionStore implements ISessionsStore {
// TODO this missing last step breaks the junit test
sessions.remove(clientID);
}
@Override
public boolean isMultiEndpointSupported() {
return supportMultiEndpoint;
}
}
@@ -35,11 +35,13 @@ import io.moquette.spi.IStore;
import io.moquette.spi.impl.ProtocolProcessor;
import io.moquette.spi.impl.ProtocolProcessorBootstrapper;
import io.moquette.spi.impl.security.AES;
import io.moquette.spi.impl.subscriptions.Token;
import io.moquette.spi.security.IAuthenticator;
import io.moquette.spi.security.IAuthorizator;
import io.moquette.spi.security.ISslContextCreator;
import io.moquette.spi.security.Tokenor;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.internal.StringUtil;
import win.liyufan.im.DBUtil;
import org.slf4j.Logger;
@@ -80,6 +82,8 @@ public class Server {
private ServerAcceptor m_acceptor;
private boolean m_shutdowning = false;
public volatile boolean m_initialized;
private ProtocolProcessor m_processor;
@@ -90,6 +94,7 @@ public class Server {
private ThreadPoolExecutorWrapper dbScheduler;
private ThreadPoolExecutorWrapper imBusinessScheduler;
private ThreadPoolExecutorWrapper callbackScheduler;
private IConfig mConfig;
@@ -239,6 +244,7 @@ public class Server {
int threadNum = Runtime.getRuntime().availableProcessors() * 2;
dbScheduler = new ThreadPoolExecutorWrapper(Executors.newScheduledThreadPool(threadNum), threadNum, "db");
imBusinessScheduler = new ThreadPoolExecutorWrapper(Executors.newScheduledThreadPool(threadNum), threadNum, "business");
callbackScheduler = new ThreadPoolExecutorWrapper(Executors.newScheduledThreadPool(1), 1, "callback");
final String handlerProp = System.getProperty(BrokerConstants.INTERCEPT_HANDLER_PROPERTY_NAME);
if (handlerProp != null) {
@@ -315,6 +321,12 @@ public class Server {
MediaServerConfig.QINIU_BUCKET_FILE_NAME = config.getProperty(BrokerConstants.QINIU_BUCKET_FILE_NAME);
MediaServerConfig.QINIU_BUCKET_FILE_DOMAIN = config.getProperty(BrokerConstants.QINIU_BUCKET_FILE_DOMAIN);
MediaServerConfig.QINIU_BUCKET_STICKER_NAME = config.getProperty(BrokerConstants.QINIU_BUCKET_STICKER_NAME);
MediaServerConfig.QINIU_BUCKET_STICKER_DOMAIN = config.getProperty(BrokerConstants.QINIU_BUCKET_STICKER_DOMAIN);
MediaServerConfig.QINIU_BUCKET_MOMENTS_NAME = config.getProperty(BrokerConstants.QINIU_BUCKET_MOMENTS_NAME);
MediaServerConfig.QINIU_BUCKET_MOMENTS_DOMAIN = config.getProperty(BrokerConstants.QINIU_BUCKET_MOMENTS_DOMAIN);
MediaServerConfig.QINIU_BUCKET_PORTRAIT_NAME = config.getProperty(BrokerConstants.QINIU_BUCKET_PORTRAIT_NAME);
MediaServerConfig.QINIU_BUCKET_PORTRAIT_DOMAIN = config.getProperty(BrokerConstants.QINIU_BUCKET_PORTRAIT_DOMAIN);
@@ -387,6 +399,14 @@ public class Server {
hazelcastInstance.getCluster().getLocalMember().setIntAttribute(HZ_Cluster_Node_ID, nodeId);
hazelcastInstance.getCluster().getLocalMember().setStringAttribute(HZ_Cluster_Node_External_IP, serverIp);
Tokenor.setKey(config.getProperty(BrokerConstants.TOKEN_SECRET_KEY));
String expirTimeStr = config.getProperty(TOKEN_EXPIRE_TIME);
if (!StringUtil.isNullOrEmpty(expirTimeStr)) {
try {
Tokenor.setExpiredTime(Long.parseLong(expirTimeStr));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
RPCCenter.getInstance().init(this);
return true;
}
@@ -405,9 +425,15 @@ public class Server {
m_processor.onRpcMsg(fromUser, clientId, message, messageId, from, request, isAdmin);
}
public boolean isShutdowning() {
return m_shutdowning;
}
public void stopServer() {
System.out.println("Server will flush data to db before shutting down, please wait 5 seconds!");
LOG.info("Unbinding server from the configured ports");
m_shutdowning = true;
m_acceptor.close();
LOG.trace("Stopping MQTT protocol processor");
m_processorBootstrapper.shutdown();
@@ -423,6 +449,7 @@ public class Server {
dbScheduler.shutdown();
imBusinessScheduler.shutdown();
callbackScheduler.shutdown();
LOG.info("Moquette server has been stopped.");
}
@@ -483,4 +510,8 @@ public class Server {
public ThreadPoolExecutorWrapper getImBusinessScheduler() {
return imBusinessScheduler;
}
public ThreadPoolExecutorWrapper getCallbackScheduler() {
return callbackScheduler;
}
}
@@ -15,6 +15,10 @@ public class MediaServerConfig {
public static String QINIU_BUCKET_VIDEO_DOMAIN;
public static String QINIU_BUCKET_FILE_NAME;
public static String QINIU_BUCKET_FILE_DOMAIN;
public static String QINIU_BUCKET_STICKER_NAME;
public static String QINIU_BUCKET_STICKER_DOMAIN;
public static String QINIU_BUCKET_MOMENTS_NAME;
public static String QINIU_BUCKET_MOMENTS_DOMAIN;
public static String QINIU_BUCKET_PORTRAIT_NAME;
public static String QINIU_BUCKET_PORTRAIT_DOMAIN;
public static String QINIU_BUCKET_FAVORITE_NAME;
@@ -70,7 +70,7 @@ public class NettyMQTTHandler extends ChannelInboundHandlerAdapter {
m_processor.processPubRel(ctx.channel(), msg);
break;
case DISCONNECT:
m_processor.processDisconnect(ctx.channel(), msg.fixedHeader().isDup());
m_processor.processDisconnect(ctx.channel(), msg.fixedHeader().isDup(), msg.fixedHeader().isRetain());
break;
case PUBACK:
m_processor.processPubAck(ctx.channel(), (MqttPubAckMessage) msg);
@@ -109,11 +109,14 @@ public class ClientSession {
}
public void disconnect(boolean cleanSession) {
public void disconnect(boolean cleanSession, boolean disableSession) {
if (cleanSession) {
LOG.info("Client disconnected. Removing its subscriptions. ClientId={}", clientID);
// cleanup topic subscriptions
cleanSession();
} else if(disableSession) {
LOG.info("Client disconnected. disable session. ClientId={}", clientID);
m_sessionsStore.disableSession(this.clientID);
}
}
@@ -30,6 +30,7 @@ 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;
@@ -104,25 +105,27 @@ 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);
long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String userId, long messageId);
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList);
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, boolean isAdmin);
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList);
ErrorCode kickoffGroupMembers(String operator, boolean isAdmin, String groupId, List<String> memberList);
ErrorCode quitGroup(String operator, String groupId);
void clearUserGroups(String userId);
ErrorCode dismissGroup(String operator, String groupId, boolean isAdmin);
ErrorCode modifyGroupInfo(String operator, String groupId, int modifyType, String value, boolean isAdmin);
ErrorCode modifyGroupAlias(String operator, String groupId, String alias);
ErrorCode modifyGroupAlias(String operator, String groupId, String alias, String memberId, boolean isAdmin);
List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests);
WFCMessage.GroupInfo getGroupInfo(String groupId);
Set<String> getUserGroupIds(String userId);
ErrorCode getGroupMembers(String groupId, long maxDt, List<WFCMessage.GroupMember> members);
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);
ErrorCode setGroupManager(String operator, String groupId, int type, List<String> userList, boolean isAdmin);
boolean isMemberInGroup(String member, String groupId);
ErrorCode canSendMessageInGroup(String member, String groupId);
Set<String> getGroupManagers(String groupId, boolean includeOwner);
ErrorCode recallMessage(long messageUid, String operatorId, boolean isAdmin);
ErrorCode recallMessage(long messageUid, String operatorId, String clientId, boolean isAdmin);
ErrorCode recallCastMessage(long messageUid, String operatorId);
void clearUserMessages(String userId);
@@ -131,6 +134,8 @@ public interface IMessagesStore {
ErrorCode getUserInfo(List<WFCMessage.UserRequest> requestList, WFCMessage.PullUserResult.Builder builder);
ErrorCode modifyUserInfo(String userId, WFCMessage.ModifyMyInfoRequest request) throws Exception;
void updateUserOnlineSetting(MemorySessionStore.Session session, boolean online);
ErrorCode modifyUserStatus(String userId, int status);
int getUserStatus(String userId);
List<InputOutputUserBlockStatus> getUserStatusList();
@@ -157,16 +162,17 @@ public interface IMessagesStore {
WFCMessage.PullMessageResult fetchChatroomMessage(String fromUser, String chatroomId, String exceptClientId, long fromMessageId);
ErrorCode verifyToken(String userId, String token, List<String> serverIPs, List<Integer> ports);
ErrorCode login(String name, String password, List<String> userIdRet);
List<FriendData> getFriendList(String userId, String clientId, long version);
void clearUserFriend(String userId);
List<WFCMessage.FriendRequest> getFriendRequestList(String userId, long version);
ErrorCode saveAddFriendRequest(String userId, WFCMessage.AddFriendRequest request, long[] head);
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);
ErrorCode SyncFriendRequestUnread(String userId, long unreadDt, long[] head);
ErrorCode isAllowUserMessage(String fromUser, String userId);
ErrorCode setFriendAliasRequest(String fromUser, String targetUserId, String alias, long[] head);
@@ -181,11 +187,12 @@ public interface IMessagesStore {
List<WFCMessage.UserSettingEntry> getUserSetting(String userId, int scope);
long updateUserSettings(String userId, WFCMessage.ModifyUserSettingReq request);
void clearUserSettings(String userId);
boolean getUserGlobalSilent(String userId);
boolean getUserGlobalSlient(String userId);
boolean getUserPushHiddenDetail(String userId);
boolean getUserConversationSlient(String userId, WFCMessage.Conversation conversation);
boolean getUserConversationSilent(String userId, WFCMessage.Conversation conversation);
boolean getSilentWhenPcOnline(String userId);
boolean isUserNoDisturbing(String userId);
ErrorCode createChannel(String operator, WFCMessage.ChannelInfo channelInfo);
void clearUserChannels(String userId);
ErrorCode modifyChannelInfo(String operator, String channelId, int modifyType, String value);
@@ -195,6 +202,7 @@ public interface IMessagesStore {
ErrorCode listenChannel(String operator, String channelId, boolean listen);
WFCMessage.ChannelInfo getChannelInfo(String channelId);
boolean checkUserInChannel(String user, String channelId);
Collection<String> getChannelSubscriber(String channelId);
Set<String> handleSensitiveWord(String message);
boolean addSensitiveWords(List<String> words);
@@ -202,6 +210,12 @@ public interface IMessagesStore {
List<String> getAllSensitiveWords();
WFCMessage.Message getMessage(long messageId);
boolean isAllowClientCustomGroupNotification();
int getVisibleQuitKickoffNotification();
List<Integer> getClientForbiddenSendTypes();
long getMessageHead(String user);
long getFriendHead(String user);
long getFriendRqHead(String user);
@@ -148,5 +148,10 @@ public interface ISessionsStore {
*/
int getSecondPhaseAckPendingMessages(String clientID);
void disableSession(String clientId);
void cleanSession(String clientID);
boolean isMultiEndpointSupported();
ErrorCode kickoffPCClient(String operator, String pcClientId);
}
@@ -16,16 +16,20 @@
package io.moquette.spi.impl;
import cn.wildfirechat.pojos.OutputMessageData;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import cn.wildfirechat.push.PushServer;
import com.google.gson.Gson;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.util.StringUtil;
import cn.wildfirechat.pojos.OutputNotifyChannelSubscribeStatus;
import cn.wildfirechat.pojos.SendMessageData;
import com.xiaoleilu.loServer.model.FriendData;
import io.moquette.persistence.*;
import io.moquette.persistence.MemorySessionStore.Session;
import io.moquette.server.ConnectionDescriptorStore;
import io.moquette.server.Server;
import io.moquette.spi.IMessagesStore;
import io.moquette.spi.ISessionsStore;
import io.netty.buffer.ByteBuf;
@@ -155,9 +159,9 @@ public class MessagesPublisher {
}
}
private void publish2Receivers(String sender, int conversationType, String target, int line, long messageHead, Collection<String> receivers, String pushContent, String exceptClientId, int pullType, int messageContentType, long serverTime, int mentionType, List<String> mentionTargets, int persistFlag) {
private void publish2Receivers(String sender, int conversationType, String target, int line, long messageHead, Collection<String> receivers, String pushContent, String pushData, String exceptClientId, int pullType, int messageContentType, long serverTime, int mentionType, List<String> mentionTargets, int persistFlag) {
if (persistFlag == Transparent) {
publishTransparentMessage2Receivers(messageHead, receivers, pullType);
publishTransparentMessage2Receivers(messageHead, receivers, pullType, exceptClientId);
return;
}
@@ -172,7 +176,7 @@ public class MessagesPublisher {
message = m_messagesStore.getMessage(messageHead);
}
final WFCMessage.Message finalMsg = message;
executorCallback.execute(() -> HttpUtils.httpJsonPost(robot.getCallback(), new Gson().toJson(SendMessageData.fromProtoMessage(finalMsg), SendMessageData.class)));
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(robot.getCallback(), new Gson().toJson(SendMessageData.fromProtoMessage(finalMsg), SendMessageData.class)));
continue;
}
}
@@ -194,6 +198,23 @@ public class MessagesPublisher {
if (pullType == ProtoConstants.PullType.Pull_ChatRoom) {
targetClients = m_messagesStore.getChatroomMemberClient(user);
}
boolean isPcOnline = false;
if (!user.equals(sender)) {
for (Session targetSession : sessions) {
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) {
boolean targetIsActive = this.connectionDescriptors.isConnected(targetSession.getClientSession().clientID);
if (targetIsActive) {
isPcOnline = true;
break;
}
}
}
}
for (Session targetSession : sessions) {
//超过7天不活跃的用户忽略
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > 7 * 24 * 60 * 60 * 1000) {
@@ -223,11 +244,13 @@ public class MessagesPublisher {
}
}
boolean isSlient;
boolean isSilent;
boolean isConvSilent = false;
if (pullType == ProtoConstants.PullType.Pull_ChatRoom) {
isSlient = true;
isSilent = true;
isConvSilent = true;
} else {
isSlient = false;
isSilent = false;
if (!user.equals(sender)) {
WFCMessage.Conversation conversation;
@@ -237,29 +260,32 @@ public class MessagesPublisher {
conversation = WFCMessage.Conversation.newBuilder().setType(conversationType).setLine(line).setTarget(target).build();
}
if (m_messagesStore.getUserConversationSlient(user, conversation)) {
if (m_messagesStore.getUserConversationSilent(user, conversation)) {
LOG.info("The conversation {}-{}-{} is slient", conversation.getType(), conversation.getTarget(), conversation.getLine());
isSlient = true;
isConvSilent = true;
}
if (m_messagesStore.getUserGlobalSlient(user)) {
if (m_messagesStore.getUserGlobalSilent(user)) {
LOG.info("The user {} is global sliented", user);
isSlient = true;
isSilent = true;
}
if (!isSilent && isPcOnline && m_messagesStore.getSilentWhenPcOnline(user)) {
LOG.info("The user {} pc online and silent when pc online", user);
isSilent = true;
}
if (!isSilent && m_messagesStore.isUserNoDisturbing(user)) {
LOG.info("The user {} is no disturbing", user);
isSilent = true;
}
}
if (!StringUtil.isNullOrEmpty(pushContent) || messageContentType == 400 || messageContentType == 402) {
if (!isSlient) {
if (!StringUtil.isNullOrEmpty(pushContent) || messageContentType == 400) {
if (!isConvSilent && (persistFlag & 0x02) > 0) {
targetSession.setUnReceivedMsgs(targetSession.getUnReceivedMsgs() + 1);
}
}
if (isSlient) {
if (mentionType == 2 || (mentionType == 1 && mentionTargets.contains(user))) {
isSlient = false;
}
}
}
boolean needPush = !user.equals(sender);
@@ -290,11 +316,11 @@ public class MessagesPublisher {
int curMentionType = 0;
if (mentionType == 2) {
curMentionType = 2;
isSlient = false;
isConvSilent = false;
} else if (mentionType == 1){
if (mentionTargets != null && mentionTargets.contains(user)) {
curMentionType = 1;
isSlient = false;
isConvSilent = false;
}
}
@@ -308,26 +334,39 @@ public class MessagesPublisher {
continue;
}
if (isSlient) {
LOG.info("Slient of user or conversation");
if (isConvSilent) {
LOG.info("Silent of user or conversation");
continue;
}
if (isSilent) {
LOG.info("Silent of user");
continue;
}
boolean isHiddenDetail = m_messagesStore.getUserPushHiddenDetail(user);
if(!nameLoaded) {
senderName = getUserDisplayName(sender);
senderName = getUserDisplayName(sender, conversationType == ProtoConstants.ConversationType.ConversationType_Group ? target : null);
targetName = getTargetName(target, conversationType);
nameLoaded = true;
}
this.messageSender.sendPush(sender, conversationType, target, line, messageHead, targetSession.getClientID(), pushContent, messageContentType, serverTime, senderName, targetName, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
String name = senderName;
if (!sender.equals(user)) {
FriendData fd = m_messagesStore.getFriendData(user, sender);
if (fd != null && !StringUtil.isNullOrEmpty(fd.getAlias())) {
name = fd.getAlias();
}
}
this.messageSender.sendPush(sender, conversationType, target, line, messageHead, targetSession.getClientID(), pushContent, pushData, messageContentType, serverTime, name, targetName, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
}
}
}
}
private void publishTransparentMessage2Receivers(long messageHead, Collection<String> receivers, int pullType) {
private void publishTransparentMessage2Receivers(long messageHead, Collection<String> receivers, int pullType, String exceptClientId) {
WFCMessage.Message message = m_messagesStore.getMessage(messageHead);
if (message != null) {
@@ -335,9 +374,16 @@ public class MessagesPublisher {
Collection<Session> sessions = m_sessionsStore.sessionForUser(user);
for (Session targetSession : sessions) {
if(System.currentTimeMillis() - targetSession.getLastActiveTime() > 60 * 60 * 1000) {
continue;
}
if (targetSession.getClientID() == null) {
continue;
}
if (targetSession.getClientID().equals(exceptClientId)) {
continue;
}
boolean targetIsActive = this.connectionDescriptors.isConnected(targetSession.getClientSession().clientID);
if (targetIsActive) {
@@ -356,33 +402,51 @@ public class MessagesPublisher {
}
}
String getUserDisplayName(String userId) {
String getUserDisplayName(String userId, String groupId) {
WFCMessage.User user = m_messagesStore.getUserInfo(userId);
String userName = null;
if(user != null) {
return user.getDisplayName();
userName = user.getDisplayName();
}
return null;
if (!StringUtil.isNullOrEmpty(groupId)) {
WFCMessage.GroupMember member = m_messagesStore.getGroupMember(groupId, userId);
if (member != null && !StringUtil.isNullOrEmpty(member.getAlias())) {
userName = member.getAlias();
}
}
return userName;
}
String getTargetName(String targetId, int cnvType) {
if (cnvType == ProtoConstants.ConversationType.ConversationType_Private) {
return getUserDisplayName(targetId);
return getUserDisplayName(targetId, null);
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Group) {
WFCMessage.GroupInfo group = m_messagesStore.getGroupInfo(targetId);
if(group != null) {
return group.getName();
}
} else if(cnvType == ProtoConstants.ConversationType.ConversationType_Channel) {
WFCMessage.ChannelInfo channelInfo = m_messagesStore.getChannelInfo(targetId);
if (channelInfo != null) {
return channelInfo.getName();
}
}
return null;
}
public void publishNotification(String topic, String receiver, long head) {
publishNotificationLocal(topic, receiver, head);
publishNotification(topic, receiver, head, null, null);
}
void publishNotificationLocal(String topic, String receiver, long head) {
public void publishNotification(String topic, String receiver, long head, String fromUser, String pushContent) {
publishNotificationLocal(topic, receiver, head, fromUser, pushContent);
}
void publishNotificationLocal(String topic, String receiver, long head, String fromUser, String pushContent) {
Collection<Session> sessions = m_sessionsStore.sessionForUser(receiver);
String fromUserName = null;
for (Session targetSession : sessions) {
boolean needPush = !StringUtil.isNullOrEmpty(pushContent);
boolean targetIsActive = this.connectionDescriptors.isConnected(targetSession.getClientSession().clientID);
if (targetIsActive) {
ByteBuf payload = Unpooled.buffer();
@@ -393,9 +457,24 @@ public class MessagesPublisher {
boolean result = this.messageSender.sendPublish(targetSession.getClientSession(), publishMsg);
if (!result) {
LOG.warn("Publish friend request failure");
} else {
needPush = false;
}
}
if (needPush) {
if (fromUserName == null) {
WFCMessage.User userInfo = m_messagesStore.getUserInfo(fromUser);
if (userInfo == null) {
fromUserName = "";
} else {
fromUserName = userInfo.getDisplayName();
}
}
if (IMTopic.NotifyFriendRequestTopic.equals(topic)) {
messageSender.sendPush(fromUser, receiver, targetSession.getClientID(), pushContent, PushServer.PushMessageType.PUSH_MESSAGE_TYPE_FRIEND_REQUEST, System.currentTimeMillis(), fromUserName, targetSession.getUnReceivedMsgs() + 1, targetSession.getLanguage());
}
}
}
}
@@ -461,7 +540,7 @@ public class MessagesPublisher {
if (message.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Channel) {
WFCMessage.ChannelInfo channelInfo = m_messagesStore.getChannelInfo(message.getConversation().getTarget());
if (channelInfo != null && !StringUtil.isNullOrEmpty(channelInfo.getCallback())) {
executorCallback.execute(() -> HttpUtils.httpJsonPost(channelInfo.getCallback() + "/message", new Gson().toJson(SendMessageData.fromProtoMessage(message), SendMessageData.class)));
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(channelInfo.getCallback() + "/message", new Gson().toJson(SendMessageData.fromProtoMessage(message), SendMessageData.class)));
}
}
long messageId = message.getMessageId();
@@ -496,18 +575,19 @@ public class MessagesPublisher {
message.getConversation().getType(), message.getConversation().getTarget(), message.getConversation().getLine(),
messageId,
receivers,
pushContent, exceptClientId, pullType, message.getContent().getType(), message.getServerTimestamp(), message.getContent().getMentionedType(), message.getContent().getMentionedTargetList(), message.getContent().getPersistFlag());
pushContent, message.getContent().getPushData(), exceptClientId, pullType, message.getContent().getType(), message.getServerTimestamp(), message.getContent().getMentionedType(), message.getContent().getMentionedTargetList(), message.getContent().getPersistFlag());
}
public void forwardMessage(final WFCMessage.Message message, String forwardUrl) {
executorCallback.execute(() -> HttpUtils.httpJsonPost(forwardUrl, new Gson().toJson(SendMessageData.fromProtoMessage(message), SendMessageData.class)));
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(forwardUrl, new Gson().toJson(OutputMessageData.fromProtoMessage(message), OutputMessageData.class)));
}
public void notifyChannelListenStatusChanged(WFCMessage.ChannelInfo channelInfo, String user, boolean listen) {
if (channelInfo == null || StringUtil.isNullOrEmpty(channelInfo.getCallback())) {
return;
}
executorCallback.execute(() -> HttpUtils.httpJsonPost(channelInfo.getCallback() + "/subscribe", new Gson().toJson(new OutputNotifyChannelSubscribeStatus(user, channelInfo.getTargetId(), listen), OutputNotifyChannelSubscribeStatus.class)));
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(channelInfo.getCallback() + "/subscribe", new Gson().toJson(new OutputNotifyChannelSubscribeStatus(user, channelInfo.getTargetId(), listen), OutputNotifyChannelSubscribeStatus.class)));
}
}
@@ -37,9 +37,18 @@ class PersistentQueueMessageSender {
this.connectionDescriptorStore = connectionDescriptorStore;
}
void sendPush(String sender, int conversationType, String target, int line, long messageHead, String deviceId, String pushContent, 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 messageHead, String deviceId, String pushContent, String pushData, int messageContentType, long serverTime, String senderName, String targetName, 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.pushContent = pushContent;
pushMessage.pushData = pushData;
PushServer.getServer().pushMessage(pushMessage, deviceId, pushContent);
}
void sendPush(String sender, String target, String deviceId, String pushContent, int pushContentType, long serverTime, String senderName, int unReceivedMsg, String language) {
LOG.info("Send push to {}, message from {}", deviceId, sender);
PushMessage pushMessage = new PushMessage(sender, target, serverTime, senderName, unReceivedMsg, language, pushContentType);
pushMessage.pushContent = pushContent;
PushServer.getServer().pushMessage(pushMessage, deviceId, pushContent);
}
@@ -75,7 +75,7 @@ public class ProtocolProcessor {
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
try {
if (descriptor != null) {
processDisconnect(descriptor.getChannel(), true);
processDisconnect(descriptor.getChannel(), true, false);
}
} catch (InterruptedException e) {
e.printStackTrace();
@@ -92,7 +92,7 @@ public class ProtocolProcessor {
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
try {
if (descriptor != null) {
processDisconnect(descriptor.getChannel(), true);
processDisconnect(descriptor.getChannel(), true, false);
}
} catch (InterruptedException e) {
e.printStackTrace();
@@ -109,8 +109,6 @@ public class ProtocolProcessor {
protected ConnectionDescriptorStore connectionDescriptors;
private boolean allowAnonymous;
private boolean allowZeroByteClientId;
private IAuthorizator m_authorizator;
private IMessagesStore m_messagesStore;
@@ -147,8 +145,6 @@ public class ProtocolProcessor {
LOG.info("Initializing MQTT protocol processor...");
this.connectionDescriptors = connectionDescriptors;
this.m_interceptor = interceptor;
this.allowAnonymous = false;
this.allowZeroByteClientId = false;
m_authorizator = authorizator;
m_authenticator = authenticator;
m_messagesStore = storageService;
@@ -199,9 +195,7 @@ public class ProtocolProcessor {
MqttVersion mqttVersion = MqttVersion.fromProtocolLevel(msg.variableHeader().version());
if (!login(channel, msg, clientId, mqttVersion)) {
MqttConnAckMessage badId = connAck(CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
channel.writeAndFlush(badId);
channel.flush();
channel.close();
LOG.error("The MQTT login failure. Username={}", payload.userName());
return;
@@ -249,17 +243,16 @@ public class ProtocolProcessor {
MemorySessionStore.Session session = m_sessionsStore.getSession(clientId);
if(session != null) {
session.refreshLastActiveTime();
forwardOnlineStatusEvent(payload.userName(), clientId, session.getPlatform(), UserOnlineStatus.ONLINE);
} else {
forwardOnlineStatusEvent(payload.userName(), clientId, ProtoConstants.Platform.Platform_UNSET, UserOnlineStatus.ONLINE);
forwardOnlineStatusEvent(payload.userName(), clientId, session.getPlatform(), UserOnlineStatus.ONLINE, session.getAppName());
m_messagesStore.updateUserOnlineSetting(session, true);
}
LOG.info("The CONNECT message has been processed. CId={}, username={}", clientId, payload.userName());
}
public void forwardOnlineStatusEvent(String userId, String clientId, int platform, int status) {
public void forwardOnlineStatusEvent(String userId, String clientId, int platform, int status, String packageName) {
if (!StringUtil.isNullOrEmpty(mUserOnlineStatusCallback)) {
executorCallback.execute(() -> HttpUtils.httpJsonPost(mUserOnlineStatusCallback, new Gson().toJson(new UserOnlineStatus(userId, clientId, platform, status))));
mServer.getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(mUserOnlineStatusCallback, new Gson().toJson(new UserOnlineStatus(userId, clientId, platform, status, packageName))));
}
}
@@ -303,6 +296,7 @@ public class ProtocolProcessor {
if (session == null) {
ErrorCode errorCode = m_sessionsStore.loadActiveSession(msg.payload().userName(), clientId);
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
failedNoSession(channel);
return false;
}
session = m_sessionsStore.getSession(clientId);
@@ -310,6 +304,7 @@ public class ProtocolProcessor {
if (session.getDeleted() != 0) {
LOG.error("user {} session {} is deleted. login failure", msg.payload().userName(), clientId);
failedNoSession(channel);
return false;
}
@@ -327,7 +322,7 @@ public class ProtocolProcessor {
return false;
}
session.setMqttVersion(mqttVersion);
} else if (!this.allowAnonymous) {
} else {
LOG.error("Client didn't supply any password and MQTT anonymous mode is disabled CId={}", clientId);
failedCredentials(channel);
return false;
@@ -339,12 +334,12 @@ public class ProtocolProcessor {
return false;
}
NettyUtils.userName(channel, msg.payload().userName());
} else if (!this.allowAnonymous) {
return true;
} else {
LOG.error("Client didn't supply any credentials and MQTT anonymous mode is disabled. CId={}", clientId);
failedCredentials(channel);
return false;
}
return true;
}
private boolean sendAck(ConnectionDescriptor descriptor, MqttConnectMessage msg, final String clientId) {
@@ -508,19 +503,19 @@ public class ProtocolProcessor {
//not use
}
public void processDisconnect(Channel channel, boolean clearSession) throws InterruptedException {
public void processDisconnect(Channel channel, boolean isDup, boolean isRetain) throws InterruptedException {
final String clientID = NettyUtils.clientID(channel);
LOG.info("Processing DISCONNECT message. CId={}, clearSession={}", clientID, clearSession);
LOG.info("Processing DISCONNECT message. CId={}, clearSession={}", clientID, isDup);
channel.flush();
if (clientID == null) {
LOG.error("Error. Cid not exist!!!", clientID, clearSession);
LOG.error("Error. Cid not exist!!!", clientID, isDup);
channel.close();
return;
}
if (!clearSession) {
processConnectionLost(clientID, channel, clearSession);
if (!isDup && !isRetain) {
processConnectionLost(clientID, channel, isDup);
return;
}
@@ -564,14 +559,15 @@ public class ProtocolProcessor {
String username = NettyUtils.userName(channel);
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
if(session != null) {
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), UserOnlineStatus.LOGOUT);
m_messagesStore.updateUserOnlineSetting(session, false);
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), UserOnlineStatus.LOGOUT, session.getAppName());
}
channel.closeFuture();
//disconnect the session
m_sessionsStore.sessionForClient(clientID).disconnect(clearSession);
m_sessionsStore.sessionForClient(clientID).disconnect(isDup, isRetain);
}
@@ -608,7 +604,8 @@ public class ProtocolProcessor {
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
if(session != null) {
session.refreshLastActiveTime();
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), clearSession ? UserOnlineStatus.LOGOUT : UserOnlineStatus.OFFLINE);
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), clearSession ? UserOnlineStatus.LOGOUT : UserOnlineStatus.OFFLINE, session.getAppName());
m_messagesStore.updateUserOnlineSetting(session, false);
}
ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel);
@@ -128,23 +128,25 @@ public class Qos1PublishHandler extends QosPublishHandler {
String userId = new String(payloadContent);
int status;
ClientSession clientSession = m_sessionStore.sessionForClient(userId);
if (clientSession == null) {
status = 2;
} else {
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(clientSession.clientID);
Collection<MemorySessionStore.Session> useSessions = m_sessionStore.sessionForUser(userId);
OutputCheckUserOnline out = new OutputCheckUserOnline();
for (MemorySessionStore.Session session : useSessions) {
if (session.getDeleted() > 0) {
continue;
}
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
if (descriptor == null) {
status = 1;
} else {
status = 0;
}
out.addSession(userId, session.getClientID(), session.getPlatform(), status, session.getLastActiveTime());
}
OutputCheckUserOnline out = new OutputCheckUserOnline();
out.setStatus(status);
RestResult result = RestResult.ok(out);
callback.onRouteHandled(new Gson().toJson(result).getBytes());
callback.onRouteHandled(new Gson().toJson(out).getBytes());
});
}

Some files were not shown because too many files have changed in this diff Show More