Commit ec13d5af by 李晓钟

Merge remote-tracking branch 'origin/feature-cluster' into feature-cluster

# Conflicts:
#	config/src/main/resources/config/application-dev.yml
parents 3b50d0b2 494cb7e1
package io.geekidea.springbootplus.test;
import com.wecloud.im.router.RouterSendService;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.utils.JsonUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.cluster.router.address.Address;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* dubbo指定ip调用测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class DubboRpcTest {
/*
* 解决log日志依赖冲突问题
*/
static {
System.setProperty("nacos.logging.default.config.enabled", "false");
}
/*
* 指定ip调用,router=address;
* injvm = false要设置成false,否则会调用到本地提供者
*/
@DubboReference(injvm = false, interfaceClass = RouterSendService.class, parameters = {"router", "address"})
private RouterSendService routerSendService;
@Test
public void test() {
int i = 0;
WsResponse wsResponse = new WsResponse();
wsResponse.setCmd(i);
wsResponse.setCode(200);
wsResponse.setMsg("i=" + i);
wsResponse.setData("hihi");
wsResponse.setReqId("123");
String msgJson = JsonUtils.encodeJson(wsResponse);
// 根据provider的ip,port创建Address实例
Address address = new Address("192.168.1.51", 20881);
RpcContext.getContext().setObjectAttachment("address", address);
routerSendService.sendMsgRemote(123L, 1, msgJson);
}
}
......@@ -23,7 +23,7 @@ public class ImConversationTest {
@Test
public void listConversation() {
List<ConversationVo> myImConversationList = imConversationMapper.getMyImConversationListAndMsgCount(1394579719625773056L, null);
List<ConversationVo> myImConversationList = imConversationMapper.getMyImConversationListAndMsgCount(1394579719625773056L,"", null);
List<ImConversation> myImConversationList1 = imConversationMapper.getMyImConversationList(1394579719625773056L);
......
......@@ -15,43 +15,34 @@ spring-boot-plus:
spring:
datasource:
url: jdbc:mysql://192.168.1.89:3306/wecloud_im_feat_cluster?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
# url: jdbc:mysql://127.0.0.1:3306/wecloud-im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
# username: root
# password: 123456
# 测试外网
url: jdbc:mysql://121.37.22.224:3306/wecloud_im_feature_cluster?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123
password: temple123456
#//测试外网
# url: jdbc:mysql://18.136.207.16:3306/wecloud_im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
# username: web
# password: axT8knPN5hAP
# Redis配置
redis:
# database: 0
# host: 127.0.0.1
# password:
# port: 6379
database: 0
host: 192.168.1.89
password:
host: 121.37.22.224
password: temple123456
port: 6379
cloud:
nacos:
discovery:
server-addr: 192.168.1.89:8848
userName: "nacos"
password: "nacos"
config:
server-addr: 192.168.1.89:8848
userName: "nacos"
password: "nacos"
file-extension: yaml
mynacos:
server-addr: 192.168.1.89:8848
dubbo:
protocol:
port: 20881
name: dubbo
registry:
address: nacos://192.168.1.89:8848?username=nacos&password=nacos
address: nacos://localhost:8848?username=nacos&password=nacos
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
mybatis-plus:
......@@ -65,6 +56,6 @@ load-blance:
# NameServer地址 用;作为地址的分隔符
rocketmq:
namesrvAddr: 192.168.1.89:9876
namesrvAddr: 127.0.0.1:9876
# 生产者的组名
producerId: im-server
\ No newline at end of file
......@@ -113,6 +113,13 @@ public class NormalChatAction {
);
if (membersList.isEmpty()) {
log.info("查询会话所有成员返回空,会话ID: {}", data.getToConversation());
WsResponse<HashMap<String, Long>> responseModel = new WsResponse<>();
ApiResult<Boolean> result = ApiResult.result(ApiCode.IS_BE_DISBAND);
responseModel.setCmd(WsResponseCmdEnum.RES.getCmdCode());
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setReqId(reqId);
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), responseModel);
return;
}
// 判断为单聊
......@@ -132,10 +139,6 @@ public class NormalChatAction {
// 再给所有人发 todo 需要改成批量
for (ImConversationMembers conversationMembers : membersList) {
// 入库 保存收件箱
long imInboxId = SnowflakeUtil.getId();
saveImInbox(imApplication, data.getToConversation(), imMessageOnlineSend.getMsgId(), conversationMembers, imInboxId);
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
......@@ -147,6 +150,10 @@ public class NormalChatAction {
// 不给自己发
continue;
}
// 入库 保存收件箱
saveImInbox(imApplication, data.getToConversation(), imMessageOnlineSend.getMsgId(),
conversationMembers, SnowflakeUtil.getId());
// 在线用户直接发消息
sendMsgForOnline(imClientReceiver.getId(), imMessageOnlineSend);
......@@ -265,7 +272,7 @@ public class NormalChatAction {
private boolean black(String reqId, ImClient imClientSender, List<ImConversationMembers> membersList, Channel channel) {
String meClientId = imClientSender.getClientId();
String heClientId;
if(membersList.get(0).getFkClientId().equals(meClientId)) {
if(membersList.get(0).getClientId() != null && membersList.get(0).getClientId().equals(meClientId)) {
heClientId = membersList.get(1).getClientId();
} else {
heClientId = membersList.get(0).getClientId();
......@@ -274,7 +281,6 @@ public class NormalChatAction {
boolean beBlack = imClientBlacklistService.isBeBlack(heClientId, meClientId);
if (beBlack) {
log.info("被对方拉黑了, meId={},heClientId={}", meClientId, heClientId);
// 响应发送方
WsResponse<HashMap<String, Long>> responseModel = new WsResponse<>();
ApiResult<Boolean> result = ApiResult.result(ApiCode.IS_BE_BLACK);
......@@ -282,9 +288,7 @@ public class NormalChatAction {
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setReqId(reqId);
channelSender.sendMsgLocal((NioSocketChannel)channel, responseModel);
return true;
}
......@@ -299,9 +303,7 @@ public class NormalChatAction {
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setReqId(reqId);
channelSender.sendMsgLocal((NioSocketChannel)channel, responseModel);
return true;
}
return false;
......
......@@ -104,6 +104,7 @@ public class ImClientController extends BaseController {
@PostMapping("/updateHeadAndNickname")
@ApiOperation(value = "添加或修改头像和昵称")
public ApiResult<Boolean> updateHeadAndNickname(@Validated(Add.class) @RequestBody ImClientHeadPortraitAndNicknameUpdate imClientHeadPortraitAndNicknameUpdate) throws Exception {
log.info("添加或修改头像和昵称入参 {}", JSON.toJSONString(imClientHeadPortraitAndNicknameUpdate));
boolean flag = imClientService.updateHeadAndNickname(imClientHeadPortraitAndNicknameUpdate);
return ApiResult.result(flag);
}
......@@ -112,6 +113,7 @@ public class ImClientController extends BaseController {
@PostMapping("/updateHeadPortrait")
@ApiOperation(value = "添加或修改头像")
public ApiResult<Boolean> updateHeadPortrait(@Validated(Add.class) @RequestBody ImClientHeadPortraitAdd imClientHeadPortraitAdd) throws Exception {
log.info("添加或修改头像入参 {}", JSON.toJSONString(imClientHeadPortraitAdd));
boolean flag = imClientService.updateHeadPortrait(imClientHeadPortraitAdd);
return ApiResult.result(flag);
}
......@@ -119,6 +121,7 @@ public class ImClientController extends BaseController {
@PostMapping("/updateNickname")
@ApiOperation(value = "添加或修改主昵称")
public ApiResult<Boolean> updateNickname(@Validated(Add.class) @RequestBody ImClientNicknameAdd imClientNicknameAdd) throws Exception {
log.info("添加或修改主昵称入参 {}", JSON.toJSONString(imClientNicknameAdd));
boolean flag = imClientService.updateNickname(imClientNicknameAdd);
return ApiResult.result(flag);
}
......@@ -132,7 +135,8 @@ public class ImClientController extends BaseController {
*/
@PostMapping("/logout")
@ApiOperation(value = "退出登陆 清除推送token等")
public ApiResult<Boolean> logout(@RequestBody @Validated LogoutParam param) throws Exception {
public ApiResult<Boolean> logout(@RequestBody @Validated LogoutParam param) {
log.info("退出登陆入参 {}", JSON.toJSONString(param));
boolean flag = imClientService.logout(param);
return ApiResult.result(flag);
}
......
package com.wecloud.im.controller;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImConversationQueryParam;
import com.wecloud.im.param.MutedGroupMemberParam;
import com.wecloud.im.param.MutedGroupParam;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.TransferOwnerParam;
......@@ -51,8 +53,10 @@ public class ImConversationController extends BaseController {
*/
@PostMapping("/saveOrUpdateName")
@ApiOperation(value = "添加或修改会话名称", notes = "权限:目前只有创建者有权限操作")
public ApiResult<Boolean> saveOrUpdateName(@RequestBody ImConversationNameUpdate imConversationNameUpdate) throws Exception {
return imConversationService.saveOrUpdateName(imConversationNameUpdate);
public ApiResult<Boolean> saveOrUpdateName(@RequestBody ImConversationNameUpdate param) {
log.info("添加或修改会话名称入参 {}", JSON.toJSONString(param));
imConversationService.saveOrUpdateName(param);
return ApiResult.ok();
}
......@@ -61,8 +65,9 @@ public class ImConversationController extends BaseController {
*/
@PostMapping("/saveOrUpdateAttr")
@ApiOperation(value = "添加或修改会话拓展字段", notes = "权限:所有client都权限操作")
public ApiResult<Boolean> saveOrUpdateAttr(@RequestBody ImConversationAttrUpdate imConversationAttrUpdate) throws Exception {
return imConversationService.saveOrUpdateAttr(imConversationAttrUpdate);
public ApiResult<Boolean> saveOrUpdateAttr(@RequestBody ImConversationAttrUpdate imConversationAttrUpdate) {
imConversationService.saveOrUpdateAttr(imConversationAttrUpdate);
return ApiResult.ok();
}
......@@ -71,7 +76,7 @@ public class ImConversationController extends BaseController {
*/
@PostMapping("/leave")
@ApiOperation(value = "client退出会话", notes = "若是创建者退出,[创建者]权限将会转移给按加入会话时间排序的下一个client")
public ApiResult<Boolean> leaveConversation(@RequestBody ImClientLeaveConversation imClientToConversation) throws Exception {
public ApiResult<Boolean> leaveConversation(@RequestBody ImClientLeaveConversation imClientToConversation) {
log.info("client退出会话入参 {}", JSON.toJSONString(imClientToConversation));
return imConversationService.leaveConversation(imClientToConversation);
}
......@@ -81,12 +86,23 @@ public class ImConversationController extends BaseController {
* 将client从会话移除
*/
@PostMapping("/delClient")
@ApiOperation(value = "将client从会话移除", notes = "权限:目前只有创建者有权限操作")
@ApiOperation(value = "将client从会话移除", notes = "权限:目前只有群主有权限操作")
public ApiResult<Boolean> delClientToConversation(@RequestBody ImClientToConversation imClientToConversation) throws Exception {
log.info("将client从会话移除入参 {}", JSON.toJSONString(imClientToConversation));
return imConversationService.delClientToConversation(imClientToConversation);
}
/**
* 解散群聊
*/
@PostMapping("/disband")
@ApiOperation(value = "解散群聊", notes = "权限:目前只有群主有权限操作")
public ApiResult<Boolean> disband(@RequestBody DisbandConversationParam param) throws Exception {
log.info("解散群聊入参 {}", JSON.toJSONString(param));
imConversationService.disband(param);
return ApiResult.ok();
}
/**
* 将用户添加进会话
......@@ -149,7 +165,7 @@ public class ImConversationController extends BaseController {
*/
@PostMapping("/mutedGroupMember")
@ApiOperation(value = "选择禁言", notes = "权限:群主和管理员有权限操作")
public ApiResult<Boolean> mutedGroupMember(@RequestBody @Validated MutedGroupParam param) {
public ApiResult<Boolean> mutedGroupMember(@RequestBody @Validated MutedGroupMemberParam param) {
log.info("选择禁言入参 {}", JSON.toJSONString(param));
if (CollectionUtils.isEmpty(param.getClientIds())) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
......@@ -163,7 +179,7 @@ public class ImConversationController extends BaseController {
*/
@PostMapping("/getList")
@ApiOperation(value = "查询加入的会话列表", notes = "查询用户加入的非隐藏状态的会话列表 与每个会话的未读条数 成员")
public ApiResult<List<ConversationVo>> getMyImConversationListAndMsgCount() throws Exception {
public ApiResult<List<ConversationVo>> getMyImConversationListAndMsgCount() {
List<ConversationVo> conversationList = imConversationService.getMyImConversationListAndMsgCount();
return ApiResult.ok(conversationList);
}
......
......@@ -40,7 +40,8 @@ public class ImConversationMembersController extends BaseController {
@PostMapping("/updateClientRemarkName")
@ApiOperation(value = "添加或修改会话成员备注", notes = "权限:目前只有client成员自己有权限操作")
public ApiResult<Boolean> saveOrUpdateClientRemarkName(@RequestBody ImConvMemeClientRemarkNameParam imConvMemeClientRemarkNameParam) throws Exception {
return imConversationMembersService.saveOrUpdateClientRemarkName(imConvMemeClientRemarkNameParam);
imConversationMembersService.saveOrUpdateClientRemarkName(imConvMemeClientRemarkNameParam);
return ApiResult.ok();
}
......
......@@ -2,6 +2,7 @@ package com.wecloud.im.controller;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import com.wecloud.im.service.ImInboxService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
......@@ -54,15 +55,15 @@ public class ImInboxController extends BaseController {
}
/**
* 整个会话消息修改为已读状态
* 会话消息修改为已读状态
*/
@PostMapping("/updateMsgReadStatusByConversation")
@ApiOperation(value = "整个会话消息修改为已读状态")
public ApiResult<Boolean> updateMsgReadStatusByConversation(@RequestBody MsgReadStatusUpdateParam msgReadStatusUpdateParam) throws Exception {
if (msgReadStatusUpdateParam.getConversationId() == null) {
@ApiOperation(value = "会话消息修改为已读状态")
public ApiResult<Boolean> updateMsgReadStatusByConversation(@RequestBody UpdateMsgReadStatusByConversationParam param) throws Exception {
if (param.getConversationId() == null) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION);
}
return ApiResult.ok(imInboxService.updateMsgReadStatusByConversation(msgReadStatusUpdateParam));
return ApiResult.ok(imInboxService.updateMsgReadStatusByConversation(param));
}
}
......
package com.wecloud.im.controller;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.multimeet.service.MultiMeetService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author wenzhida
* @Date 2022/3/7 18:08
* @Description 多人音视频通话控制器
*/
@Slf4j
@RestController
@RequestMapping("/multiMeet")
@Api(value = "多人音视频通话", tags = {"多人音视频通话"})
public class ImMultiMeetController extends BaseController {
@Autowired
private MultiMeetService multiMeetService;
/**
* 并邀请客户端加入
*/
@PostMapping("/invite")
@ApiOperation(value = "邀请加入多人音视频会议", notes = "邀请加入多人音视频会议")
public ApiResult<Boolean> invite(@RequestBody InviteToMultiMeetParam param) {
log.info("邀请加入多人音视频会议入参 {}", JSON.toJSONString(param));
if (CollectionUtils.isEmpty(param.getToClients())) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
multiMeetService.invite(param);
return ApiResult.ok();
}
@PostMapping("/reject")
@ApiOperation(value = "拒接进入会议", notes = "拒接进入会议")
public ApiResult<Boolean> reject(@RequestBody RejectToMultiMeetParam param) {
log.info("拒绝加入多人音视频会议入参 {}", JSON.toJSONString(param));
multiMeetService.reject(param);
return ApiResult.ok();
}
@PostMapping("/agree")
@ApiOperation(value = "同意进入会议", notes = "同意进入会议")
public ApiResult<Boolean> agree(@RequestBody AgreeToMultiMeetParam param) {
multiMeetService.agree(param);
return ApiResult.ok();
}
@PostMapping("/leave")
@ApiOperation(value = "主动挂断(离开会议)", notes = "主动挂断(离开会议)")
public ApiResult<Boolean> leave(@RequestBody LeaveFromMultiMeetParam param) {
multiMeetService.leave(param);
return ApiResult.ok();
}
}
......@@ -42,7 +42,7 @@ public class ImRtcController extends BaseController {
*/
@PostMapping("/createAndCall")
@ApiOperation(value = "创建频道,并邀请客户端加入", notes = "创建频道,并邀请客户端加入")
public ApiResult<CreateRtcChannelResult> createAndCall(@RequestBody CreateRtcChannelParam createRtcChannelParam) throws Exception {
public ApiResult<CreateRtcChannelResult> createAndCall(@RequestBody CreateRtcChannelParam createRtcChannelParam) {
if (BaseEnum.valueOf(CallTypeEnum.class, createRtcChannelParam.getCallType()) == null) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
......
package com.wecloud.im.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
/**
* @Author wenzhida
* @Date 2022/3/11 16:24
* @Description 消息是否已读枚举
*/
public enum ReadMsgStatusEnum implements BaseEnum {
/**
* 0 - 未读
*/
UNREAD(0, "未读"),
/**
* 1 - 已读
*/
READ(1, "已读");
ReadMsgStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
private final Integer code;
private final String desc;
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getDesc() {
return this.desc;
}
}
package com.wecloud.im.externalaccess.controller;
import cn.hutool.crypto.digest.MD5;
import com.wecloud.im.externalaccess.param.MultiMeetSignGetParam;
import com.wecloud.im.externalaccess.param.SendVerifyCodeParam;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author wenzhida
* @Date 2022/3/3 17:39
* @Description 多人音视频控制器
*/
@Slf4j
@RestController
@RequestMapping("/multiMeet")
@Api(value = "多人音视频API", tags = {"多人音视频"})
public class MultiMeetController extends BaseController {
/**
* 获取sign
*/
@PostMapping("/getSign")
@ApiOperation(value = "获取多人音视频专用sign")
public ApiResult<String> sendVerifyCode(@RequestBody @Validated MultiMeetSignGetParam param) {
String sign = new MD5().digestHex(param.getTimestamp() + param.getClientId()
+ param.getAppKey() + param.getAppSecret() + param.getPlatform());
return ApiResult.ok(sign);
}
}
package com.wecloud.im.externalaccess.param;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/3 17:42
* @Description 多人音视频sign获取入参
*/
@Data
public class MultiMeetSignGetParam implements Serializable {
private static final long serialVersionUID = 1538118936608500035L;
@ApiModelProperty("时间戳")
@NotNull(message = "时间戳不能为空")
private String timestamp;
@ApiModelProperty("client客户端id")
@NotNull(message = "client客户端id不能为空")
private String clientId;
@ApiModelProperty("appKey")
@NotNull(message = "appKey不能为空")
private String appKey;
@ApiModelProperty("客户端平台: 1 web, 2 安卓, 3 ios, 4 pc-win, 5 pc-macOs")
@NotNull(message = "客户端平台不能为空")
private Integer platform;
@ApiModelProperty("密钥")
@NotNull(message = "密钥不能为空")
private String appSecret;
}
......@@ -24,6 +24,9 @@ public class UserBaseDto implements Serializable {
@ApiModelProperty("蓝豆号")
private String idNumber;
@ApiModelProperty("手机号码")
private String phone;
/**
* 性别
* @see com.wecloud.im.enums.SexEnum
......
......@@ -218,6 +218,7 @@ public class UserService extends BaseServiceImpl<UserMapper, User> {
UserBaseDto userBaseDto = new UserBaseDto();
BeanUtils.copyProperties(user, userBaseDto);
userBaseDto.setUserId(user.getId().toString());
userBaseDto.setPhone(user.getPhone());
return userBaseDto;
}
......
......@@ -72,7 +72,6 @@ public class FriendEventSender {
}
public void sendFriendApproveEventMsg(ImClient claimerClient, ImClient receiveClient, boolean isAgree, String rejectRemark) {
FriendApproveEventDto approveDto = new FriendApproveEventDto();
approveDto.setSubCmd(EventResponseSubCmdEnum.FRIEND_APPROVE.getCode());
approveDto.setAgree(isAgree);
......
......@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.friend.entity.ImFriend;
......@@ -101,7 +102,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
if(StringUtils.isNotEmpty(friendName)) {
my.setFriendName(friendName);
}
this.updateByKeyAndClaimer(my);
this.updateByKey(my);
} else {
my.setId(SnowflakeUtil.getId());
my.setCreateTime(new Date());
......@@ -118,10 +119,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
if(StringUtils.isNotEmpty(requestRemark)) {
friend.setRequestRemark(requestRemark);
}
if(StringUtils.isNotEmpty(friendName)) {
friend.setFriendName(friendName);
}
this.updateByKeyAndClaimer(friend);
this.updateByKey(friend);
} else {
friend.setId(SnowflakeUtil.getId());
friend.setCreateTime(new Date());
......@@ -137,7 +135,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
/**
* 根据 自己id和好友id查询好友信息
* 根据 自己id和好友id查询好友信息 - 待确认、已确认
* @param clientId
* @param friendClientId
* @return
......@@ -163,6 +161,19 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
}
/**
* 根据 自己id和好友id,更新好友信息
* @param imFriend
*/
public boolean updateByKey(ImFriend imFriend) {
// 不更新id
imFriend.setId(null);
imFriend.setCreateTime(null);
return this.update(imFriend, new QueryWrapper<ImFriend>().lambda()
.eq(ImFriend::getClientId, imFriend.getClientId())
.eq(ImFriend::getClientIdFriend, imFriend.getClientIdFriend()));
}
/**
* 好友通过/拒绝
* @param currentClient
* @param friendClient
......@@ -184,7 +195,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
if(StringUtils.isNotEmpty(rejectRemark)) {
friend.setRejectRemark(rejectRemark);
}
boolean ok1 = this.updateByKeyAndClaimer(friend);
boolean ok1 = this.updateByKey(friend);
// 同时更新我的
ImFriend my = new ImFriend();
my.setClientId(currentClient.getClientId());
......@@ -194,10 +205,8 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
if(StringUtils.isNotEmpty(rejectRemark)) {
my.setRejectRemark(rejectRemark);
}
boolean ok2 = this.updateByKeyAndClaimer(my);
boolean ok2 = this.updateByKey(my);
friendEventSender.sendFriendApproveEventMsg(currentClient, friendClient, agree, rejectRemark);
return ok1 || ok2;
}
......
......@@ -21,7 +21,7 @@ public interface ImClientBlacklistMapper extends BaseMapper<ImClientBlacklist> {
/**
* 查询我的拉黑列表
*
* @param page
* @param clientId
* @return
*/
......
......@@ -46,7 +46,7 @@ public interface ImConversationMapper extends BaseMapper<ImConversation> {
* @param currentClientId
* @return
*/
List<ConversationVo> getMyImConversationListAndMsgCount(@Param("currentClientId") Long currentClientId, @Param("conversationId") Long conversationId);
List<ConversationVo> getMyImConversationListAndMsgCount(@Param("currentClientId") Long currentClientId,@Param("clientId") String clientId, @Param("conversationId") Long conversationId);
/**
* 查询用户加入的所有会话
......
......@@ -60,4 +60,12 @@ public interface ImConversationMembersMapper extends BaseMapper<ImConversationMe
* @param fkClientIds
*/
void setAdminsForConversation(@Param("conversationId") Long conversationId, @Param("fkClientIds") List<Long> fkClientIds, @Param("role") Integer role);
/**
* 根据会话id删除群成员
* @param conversationId
*/
void deleteByConversationId(@Param("conversationId") Long conversationId);
}
......@@ -107,6 +107,7 @@ public class MqSender {
new QueryWrapper<ImClientDevice>().lambda()
.eq(ImClientDevice::getFkClientId, imClientReceiver.getId()));
if (CollectionUtils.isEmpty(clientDeviceList)) {
log.info("接收人信息 {} 查无推送设备", imClientReceiver.getId());
return null;
}
List<ClientDeviceDTO> deviceDTOList = Lists.newArrayList();
......@@ -115,6 +116,7 @@ public class MqSender {
clientDeviceDTO.setValid(imClientDevice.getValid());
clientDeviceDTO.setDeviceType(imClientDevice.getDeviceType());
clientDeviceDTO.setDeviceToken(imClientDevice.getDeviceToken());
deviceDTOList.add(clientDeviceDTO);
}
clientDTO.setDeviceDTOList(deviceDTOList);
messageDTO.setClientDTO(clientDTO);
......
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:18
* @Description 同意加入会议
*/
@Data
@ApiModel(value = "同意加入会议")
public class AgreeToMultiMeetParam implements Serializable {
private static final long serialVersionUID = -5450997250608231171L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
@ApiModelProperty(value = "发起会议人clientId", required = true)
private String inviterClientId;
}
......@@ -40,6 +40,11 @@ public class ChatContentVo extends BaseRequest {
*/
String text;
/**
* 被@人clientId, 多人用英文逗号分隔; @所有人 入参为 -1
*/
String at;
public PushVO getPush() {
return JsonUtils.beanCopyDeep(this.get("push"), PushVO.class);
}
......@@ -73,6 +78,14 @@ public class ChatContentVo extends BaseRequest {
this.text = text;
}
public String getAt() {
return this.get("at") + "";
}
public void setAt(String at) {
this.at = at;
}
@Override
public String getReqId() {
return reqId;
......
package com.wecloud.im.param;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Author wenzhida
* @Date 2022/3/9 20:54
* @Description 解散群聊入参
*/
@Data
@ApiModel(value = "解散群聊入参")
public class DisbandConversationParam extends BaseEntity {
private static final long serialVersionUID = -354476295467898641L;
@ApiModelProperty("会话表id")
private Long conversationId;
}
......@@ -36,4 +36,9 @@ public class ImHistoryMessagePageParam extends BasePageOrderParam {
*/
@ApiModelProperty("消息id最大值")
private Long msgIdEnd;
/**
* 当前操作人client主键id
*/
private Long currentFkClientId;
}
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @Author wenzhida
* @Date 2022/3/7 19:09
* @Description 邀请加入多人会议室
*/
@Data
@ApiModel(value = "邀请加入多人会议室")
public class InviteToMultiMeetParam implements Serializable {
private static final long serialVersionUID = 6815250319056125934L;
@ApiModelProperty(value = "绑定的会话id,可选", required = false)
private Long conversationId;
@NotNull(message = "多人会议房间id不可为空")
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
@NotNull(message = "被邀请的客户端ID列表不可为空")
@ApiModelProperty(value = "被邀请的客户端ID列表", required = true)
private List<String> toClients;
@ApiModelProperty(value = "接收方展示的系统推送内容", required = false)
private String push;
@ApiModelProperty(value = "是否需要给对方发系统通知", required = true)
private Boolean pushCall;
}
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:18
* @Description 离开会议
*/
@Data
@ApiModel(value = "离开会议")
public class LeaveFromMultiMeetParam implements Serializable {
private static final long serialVersionUID = 5395668355528734094L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
@ApiModelProperty(value = "发起会议人clientId", required = true)
private String inviterClientId;
}
package com.wecloud.im.param;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author wenzhida
* @Date 2022/2/17 15:58
* @Description 群成员禁言入参
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "群成员禁言入参")
public class MutedGroupMemberParam extends BaseEntity {
private static final long serialVersionUID = 7572911152462759853L;
@NotNull
@ApiModelProperty("会话id")
private Long conversationId;
@ApiModelProperty("禁言指定群成员列表 - 群禁言无需入参")
private List<String> clientIds;
@NotNull
@ApiModelProperty("禁言类型 1-取消禁言 2-禁言")
private Integer mutedType;
}
package com.wecloud.im.param;
import com.wecloud.im.enums.MutedEnum;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -7,7 +8,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author wenzhida
......@@ -25,9 +25,10 @@ public class MutedGroupParam extends BaseEntity {
@ApiModelProperty("会话id")
private Long conversationId;
@ApiModelProperty("禁言指定群成员列表 - 群禁言无需入参")
private List<String> clientIds;
/**
* 禁言类型
* @see com.wecloud.im.enums.MutedEnum
*/
@NotNull
@ApiModelProperty("禁言类型 1-取消禁言 2-禁言")
private Integer mutedType;
......
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Author wenzhida
* @Date 2022/3/7 22:18
* @Description 拒接加入会议
*/
@Data
@ApiModel(value = "拒接加入会议")
public class RejectToMultiMeetParam implements Serializable {
private static final long serialVersionUID = -249558750895602938L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
@ApiModelProperty(value = "发起会议人clientId", required = true)
private String inviterClientId;
}
package com.wecloud.im.param;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author wenzhida
* @Date 2022/3/8 11:11
* @Description 给会话消息设置已读入参
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "给会话消息设置已读入参")
public class UpdateMsgReadStatusByConversationParam extends BaseEntity {
private static final long serialVersionUID = 4378221788952403799L;
@ApiModelProperty("会话id")
@NotNull(message = "会话id不能为空")
private Long conversationId;
@ApiModelProperty("最新一条消息id 将这条消息及之前的消息全部设置为已读")
@NotNull(message = "最新一条消息id不能为空")
private Long msgIdEnd;
}
package com.wecloud.im.router;
import com.wecloud.im.ws.sender.ChannelSender;
import io.geekidea.springbootplus.framework.util.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
@DubboService
public class RouterSendServiceImpl implements RouterSendService {
......@@ -16,6 +19,7 @@ public class RouterSendServiceImpl implements RouterSendService {
@Override
public void sendMsgRemote(Long clientId, Integer platform, String msg) {
log.info("接收到rpc调用,本地ip {}", IpUtil.getLocalhostIp());
channelSender.sendMsgLocal(clientId, platform, msg);
}
......
......@@ -33,7 +33,7 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception;
ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
/**
* 移出黑名单
......@@ -42,7 +42,7 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception;
ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
/**
* 获取分页对象
......@@ -50,6 +50,6 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam) throws Exception;
ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam);
}
......@@ -36,7 +36,12 @@ public interface ImConversationMembersService extends BaseService<ImConversation
ApiResult<List<ApiImConversationMembersQueryVo>> getRestApiImConversationMembersList(ApiImConversationMembersPageParam apiImConversationMembersPageParam, ImApplication imApplication);
ApiResult<Boolean> saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam imConvMemeClientRemarkNameParam);
/**
* 添加或修改会话成员备注
* @param param
* @return
*/
void saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam param);
/**
......@@ -76,7 +81,13 @@ public interface ImConversationMembersService extends BaseService<ImConversation
* @return
* @throws Exception
*/
boolean deleteImConversationMembers(Long id) throws Exception;
boolean deleteImConversationMembers(Long id);
/**
* 根据会话id做删除
* @param conversationId 会话id
*/
void deleteByConversationId(Long conversationId);
/**
* 根据ID获取查询对象
......
......@@ -2,9 +2,11 @@ package com.wecloud.im.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImConversationPageParam;
import com.wecloud.im.param.ImConversationQueryParam;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.param.MutedGroupMemberParam;
import com.wecloud.im.param.MutedGroupParam;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.TransferOwnerParam;
......@@ -68,9 +70,16 @@ public interface ImConversationService extends BaseService<ImConversation> {
ApiResult<Boolean> delClientToConversation(ImClientToConversation imClientToConversation) throws Exception;
/**
* 解散群聊
* @param param
* @return
*/
void disband(DisbandConversationParam param);
/**
* client退出会话
*/
ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation) throws Exception;
ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation);
/**
* 群主转让
......@@ -98,7 +107,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @param param
* @return
*/
Boolean mutedGroupMember(@RequestBody MutedGroupParam param);
Boolean mutedGroupMember(@RequestBody MutedGroupMemberParam param);
/**
* 判断当前操作人是否为指定角色成员
......@@ -112,12 +121,12 @@ public interface ImConversationService extends BaseService<ImConversation> {
/**
* 添加或修改会话名称
*/
ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate imConversationNameUpdate) throws Exception;
ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate imConversationNameUpdate);
/**
* 添加或修改会话拓展字段
*/
ApiResult<Boolean> saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate) throws Exception;
void saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate);
/**
* 修改
......@@ -126,7 +135,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @return
* @throws Exception
*/
boolean updateImConversation(ImConversation imConversation) throws Exception;
boolean updateImConversation(ImConversation imConversation);
/**
* 修改为 是否单向隐藏会话","云端聊天记录不删除;假设有A和B两个用户,A删会话,B还能发; 如果B发了消息,A这边要重新把会话显示出来,并能显示之前的聊天记录"
......@@ -160,7 +169,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @return
* @throws Exception
*/
Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam) throws Exception;
Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam);
/**
......@@ -169,14 +178,14 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @return
* @throws Exception
*/
List<ConversationVo> getMyImConversationListAndMsgCount() throws Exception;
List<ConversationVo> getMyImConversationListAndMsgCount();
/**
* 根据会话id查询单个会话信息 与会话的未读条数
* @param param
* @return
*/
ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param) throws Exception;
ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param);
/**
* 获取加入的所有会话
......@@ -184,7 +193,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @return
* @throws Exception
*/
List<ImConversation> getMyImConversationList() throws Exception;
List<ImConversation> getMyImConversationList();
/**
* 判断重复会话中的Attributes是否一样
......
......@@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
......@@ -86,9 +87,9 @@ public interface ImInboxService extends BaseService<ImInbox> {
/**
* 整个会话消息修改为已读状态
* @param msgReadStatusUpdateParam
* @param param
* @return
*/
Boolean updateMsgReadStatusByConversation(MsgReadStatusUpdateParam msgReadStatusUpdateParam);
Boolean updateMsgReadStatusByConversation(UpdateMsgReadStatusByConversationParam param);
}
......@@ -74,11 +74,11 @@ public interface ImMessageService extends BaseService<ImMessage> {
/**
* 查询某个会话历史消息分页列表
*
* @param imHistoryMessagePageParam
* @param param
* @return
* @throws Exception
*/
Paging<OfflineMsgDto> getHistoryMsgConversationId(ImHistoryMessagePageParam imHistoryMessagePageParam);
Paging<OfflineMsgDto> getHistoryMsgConversationId(ImHistoryMessagePageParam param);
/**
* 查询用户所有离线消息
......
......@@ -51,13 +51,13 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception {
ImClient client = imClientService.getCurrentClient();
if (client == null) {
public ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
ImClient currentClient = imClientService.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
ImClient beBlacker = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, client.getFkAppid())
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getClientId, imClientBlacklistUpdate.getClientIdBePrevent()));
if (beBlacker == null) {
throw new BusinessException("查无用户信息");
......@@ -65,8 +65,8 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
ImClientBlacklist imClientBlacklist = new ImClientBlacklist();
imClientBlacklist.setId(SnowflakeUtil.getId());
imClientBlacklist.setCreateTime(new Date());
imClientBlacklist.setFkAppid(client.getFkAppid());
imClientBlacklist.setClientIdPrevent(client.getClientId());
imClientBlacklist.setFkAppid(currentClient.getFkAppid());
imClientBlacklist.setClientIdPrevent(currentClient.getClientId());
imClientBlacklist.setClientIdBePrevent(beBlacker.getClientId());
this.save(imClientBlacklist);
......@@ -75,37 +75,32 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception {
public ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
// 操作者
ImClient client = imClientService.getCurrentClient();
if (client == null) {
ImClient currentClient = imClientService.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
// 被拉黑者
ImClient beBlacker = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, client.getFkAppid())
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getClientId, imClientBlacklistUpdate.getClientIdBePrevent()));
if (beBlacker == null) {
throw new BusinessException("查无用户信息");
}
// 删除
this.remove(new QueryWrapper<ImClientBlacklist>().lambda()
.eq(ImClientBlacklist::getClientIdPrevent, client.getClientId())
.eq(ImClientBlacklist::getClientIdPrevent, currentClient.getClientId())
.eq(ImClientBlacklist::getClientIdBePrevent, beBlacker.getClientId()));
return ApiResult.ok();
}
@Override
public ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam) throws Exception {
public ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam) {
Page<ImClientBlacklistQueryVo> page = new PageInfo<>(imClientBlacklistPageParam);
ImClient client = imClientService.getCurrentClient();
IPage<ImClientBlacklistQueryVo> imClientBlacklistPageList = imClientBlacklistMapper.getImClientBlacklistPageList(page, client.getClientId());
ImClient currentClient = imClientService.getCurrentClient();
IPage<ImClientBlacklistQueryVo> imClientBlacklistPageList = imClientBlacklistMapper.getImClientBlacklistPageList(page, currentClient.getClientId());
Paging<ImClientBlacklistQueryVo> imClientBlacklistQueryVoPaging = new Paging<>(imClientBlacklistPageList);
return ApiResult.ok(imClientBlacklistQueryVoPaging);
}
......
package com.wecloud.im.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.mapper.ImConversationMembersMapper;
import com.wecloud.im.param.ApiImConversationMembersPageParam;
......@@ -23,9 +26,14 @@ import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
......@@ -36,7 +44,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 会话成员表 服务实现类
......@@ -81,51 +92,67 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam imConvMemeClientRemarkNameParam) {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
ImClient imClientSender = imClientService.getCurrentClient();
public void saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 查询该成员
ImConversationMembers imConversationMember = imConversationMembersService.getOne(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, imApplication.getId())
.eq(ImConversationMembers::getFkConversationId, imConvMemeClientRemarkNameParam.getConversationId())
.eq(ImConversationMembers::getFkClientId, imClientSender.getId())
.eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.eq(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (imConversationMember == null) {
return ApiResult.fail();
throw new BusinessException("未查询到会话成员信息");
}
// // 查询该会话所有成员
// List<ImConversationMembers> membersList = imConversationMembersService.list(
// new QueryWrapper<ImConversationMembers>().lambda()
// .eq(ImConversationMembers::getFkAppid, imApplication.getId())
// .eq(ImConversationMembers::getFkConversationId, imConversationAttrUpdate.getConversationId())
// .notIn(ImConversationMembers::getId, imClientSender.getId())
// );
imConversationMember.setClientRemarkName(imConvMemeClientRemarkNameParam.getClientRemarkName());
imConversationMember.setClientRemarkName(param.getClientRemarkName());
boolean b = imConversationMembersService.updateById(imConversationMember);
if (b) {
//TODO ws下发群成员备注变动事件
return ApiResult.ok();
} else {
return ApiResult.fail();
if (!b) {
throw new BusinessException("修改群成员备注失败");
}
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.ne(ImConversationMembers::getFkClientId, currentClient.getId())
);
for (ImConversationMembers member : membersList) {
// 不关心事件是否发送成功
try {
// 给所有成员下发事件消息
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getId, member.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setType(MsgTypeEnum.CONVERSATION_MEMBER_NAME_MODIFY.getUriCode());
imMessageOnlineSend.setSender(currentClient.getClientId());
Map<String, Object> content = Maps.newHashMap();
content.put("operator", currentClient.getClientId());
content.put("remarkName", param.getClientRemarkName());
imMessageOnlineSend.setContent(content);
imMessageOnlineSend.setConversationId(param.getConversationId());
imMessageOnlineSend.setWithdraw(Boolean.FALSE);
imMessageOnlineSend.setEvent(Boolean.TRUE);
// 向接收方推送
WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.CONVERSATION_EVENT_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(imMessageOnlineSend);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, imClientReceiver.getId());
} catch (Exception e) {
log.info("下发解散群事件失败,接收人 {}", JSON.toJSONString(member));
}
}
}
@Override
......@@ -197,11 +224,16 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
@Transactional(rollbackFor = Exception.class)
@Override
public boolean deleteImConversationMembers(Long id) throws Exception {
public boolean deleteImConversationMembers(Long id) {
return super.removeById(id);
}
@Override
public void deleteByConversationId(Long conversationId) {
imConversationMembersMapper.deleteByConversationId(conversationId);
}
@Override
public ImConversationMembersQueryVo getImConversationMembersById(Long id) throws Exception {
return imConversationMembersMapper.getImConversationMembersById(id);
}
......
package com.wecloud.im.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
......@@ -15,12 +16,15 @@ import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.ChatTypeEnum;
import com.wecloud.im.enums.GroupRoleEnum;
import com.wecloud.im.enums.MutedEnum;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.ImConversationPageParam;
import com.wecloud.im.param.ImConversationQueryParam;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.MutedGroupMemberParam;
import com.wecloud.im.param.MutedGroupParam;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.TransferOwnerParam;
......@@ -35,9 +39,9 @@ import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.vo.ConversationVo;
import com.wecloud.im.vo.ImConversationCreateVo;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
......@@ -178,7 +182,6 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
return ApiResult.ok(imConversationCreateVo);
}
}
}
// 会话id
......@@ -209,9 +212,11 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
ImConversationMembers imConversationMembers = new ImConversationMembers();
imConversationMembers.setId(imConversationMembersId);
imConversationMembers.setCreateTime(new Date());
imConversationMembers.setUpdateTime(new Date());
imConversationMembers.setFkAppid(createClient.getFkAppid());
imConversationMembers.setFkConversationId(imConversationId);
imConversationMembers.setFkClientId(creator);
imConversationMembers.setClientId(createClient.getClientId());
imConversationMembers.setRole(GroupRoleEnum.OWNER.getCode());
imConversationMembersService.save(imConversationMembers);
......@@ -220,13 +225,14 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, createClient.getFkAppid())
.eq(ImClient::getClientId, id));
Long imConversationMembersId2 = SnowflakeUtil.getId();
ImConversationMembers imConversationMembers2 = new ImConversationMembers();
imConversationMembers2.setId(imConversationMembersId2);
imConversationMembers2.setId(SnowflakeUtil.getId());
imConversationMembers2.setCreateTime(new Date());
imConversationMembers2.setUpdateTime(new Date());
imConversationMembers2.setFkAppid(createClient.getFkAppid());
imConversationMembers2.setFkConversationId(imConversationId);
imConversationMembers2.setFkClientId(client2.getId());
imConversationMembers2.setClientId(client2.getClientId());
imConversationMembers2.setRole(GroupRoleEnum.NORMAL.getCode());
imConversationMembersService.save(imConversationMembers2);
if (imConversationCreate.getClientIds().size() > 1) {
......@@ -275,7 +281,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
.eq(ImConversationMembers::getFkAppid, imApplication.getId())
.eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
.notIn(ImConversationMembers::getId, imClientSender.getId())
.ne(ImConversationMembers::getFkClientId, imClientSender.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
......@@ -306,11 +312,14 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
Long imConversationMembersId2 = SnowflakeUtil.getId();
ImConversationMembers imConversationMembers2 = new ImConversationMembers();
imConversationMembers2.setUpdateTime(new Date());
imConversationMembers2.setId(imConversationMembersId2);
imConversationMembers2.setCreateTime(new Date());
imConversationMembers2.setFkAppid(imApplication.getId());
imConversationMembers2.setFkConversationId(imClientToConversation.getConversationId());
imConversationMembers2.setFkClientId(clientToConversation.getId());
imConversationMembers2.setClientId(clientToConversation.getClientId());
imConversationMembers2.setMuted(MutedEnum.NO.getCode());
imConversationMembers2.setRole(GroupRoleEnum.NORMAL.getCode());
imConversationMembersService.save(imConversationMembers2);
......@@ -396,14 +405,11 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> delClientToConversation(ImClientToConversation imClientToConversation) throws Exception {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
ImClient imClientSender = imClientService.getCurrentClient();
// 判断是否为群主
ImConversationMembers conversationMember = imConversationMembersService.getOne(
new QueryWrapper<ImConversationMembers>().lambda()
......@@ -418,7 +424,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, imApplication.getId())
.eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
.notIn(ImConversationMembers::getId, imClientSender.getId())
.ne(ImConversationMembers::getFkClientId, imClientSender.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
......@@ -426,10 +432,9 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
}
int needAddCount = 0;
// 将client从会话移除
for (String clientId : imClientToConversation.getClientIds()) {
ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
ImClient clientToBeRemove = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getClientId, clientId));
......@@ -437,26 +442,23 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
ImConversationMembers members = imConversationMembersService.getOne(new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, imApplication.getId())
.eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
.eq(ImConversationMembers::getFkClientId, client2.getId())
.eq(ImConversationMembers::getFkClientId, clientToBeRemove.getId())
);
// 则跳过
if (members == null) {
continue;
}
imConversationMembersService.deleteImConversationMembers(members.getId());
// ws移除事件通知给群内其他人 ----------
needAddCount--;
// 生成消息id
long messageId = SnowflakeUtil.getId();
ImMessage imMessage = new ImMessage();
Map<String, Object> content = new HashMap<>();
content.put("operator", imClientSender.getClientId()); //操作的client ID
content.put("passivityOperator", client2.getClientId()); //被操作的client ID
content.put("passivityOperator", clientToBeRemove.getClientId()); //被操作的client ID
imMessage.setContent(JsonUtils.encodeJson(content));
// 保存消息至消息表
imMessage.setId(messageId);
imMessage.setMsgType(MsgTypeEnum.REMOVE_CLIENT_CONVERSATION.getUriCode());
......@@ -470,9 +472,9 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
imMessage.setFkConversationId(imClientToConversation.getConversationId());
imMessageService.save(imMessage);
membersList.removeIf(e -> e.getId().equals(members.getId()));
// 遍历发送
for (ImConversationMembers conversationMembers : membersList) {
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
......@@ -483,7 +485,6 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
imMessageOnlineSend.setMsgId(messageId);
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setType(imMessage.getMsgType());
......@@ -507,14 +508,90 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 将群成员数量减
imConversationMapper.addMemberCount(imApplication.getId(), imClientToConversation.getConversationId(), needAddCount);
return ApiResult.ok();
}
@Override
public void disband(DisbandConversationParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 判断是否为群主
ImConversationMembers conversationMember = imConversationMembersService.getOne(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.eq(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (conversationMember == null || !GroupRoleEnum.OWNER.getCode().equals(conversationMember.getRole())) {
throw new BusinessException("非群主无权限解散群聊");
}
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.ne(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (membersList.isEmpty()) {
throw new BusinessException("群聊成员列表为空");
}
// 删除所有成员
imConversationMembersService.deleteByConversationId(param.getConversationId());
// 保存事件消息
ImMessage imMessage = new ImMessage();
Map<String, Object> content = new HashMap<>();
content.put("operator", currentClient.getClientId());
imMessage.setContent(JsonUtils.encodeJson(content));
// 保存消息至消息表
imMessage.setId(SnowflakeUtil.getId());
imMessage.setMsgType(MsgTypeEnum.CONVERSATION_DISBAND.getUriCode());
imMessage.setCreateTime(new Date());
imMessage.setFkAppid(currentClient.getFkAppid());
imMessage.setSender(currentClient.getId());
imMessage.setWithdraw(false);
imMessage.setEvent(true);
imMessage.setSystemFlag(false);
imMessage.setSendStatus(2);
imMessage.setFkConversationId(param.getConversationId());
imMessageService.save(imMessage);
for (ImConversationMembers member : membersList) {
// 不关心事件是否发送成功
try {
// 给所有成员下发事件消息
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getId, member.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
imMessageOnlineSend.setMsgId(imMessage.getId());
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setType(imMessage.getMsgType());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setContent(content);
imMessageOnlineSend.setConversationId(param.getConversationId());
imMessageOnlineSend.setWithdraw(Boolean.FALSE);
imMessageOnlineSend.setEvent(Boolean.TRUE);
// 向接收方推送
WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.CONVERSATION_EVENT_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(imMessageOnlineSend);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, imClientReceiver.getId());
} catch (Exception e) {
log.info("下发解散群事件失败,接收人 {}", JSON.toJSONString(member));
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation) throws Exception {
public ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation) {
ImClient currentClient = imClientService.getCurrentClient();
ImConversation imConversation = imConversationService.getById(imClientToConversation.getConversationId());
......@@ -527,7 +604,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
.orderByAsc(ImConversationMembers::getCreateTime)
.notIn(ImConversationMembers::getFkClientId, currentClient.getId())
.ne(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (membersList.isEmpty()) {
......@@ -545,7 +622,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 将client从会话移除
boolean b = imConversationMembersService.deleteImConversationMembers(members.getId());
if (!b) {
throw new Exception("deleteImConversationMembers");
throw new BusinessException("退出群聊错误");
}
// 将群成员数量减1
......@@ -571,7 +648,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
imMessage.setFkConversationId(imClientToConversation.getConversationId());
boolean save = imMessageService.save(imMessage);
if (!save) {
throw new Exception("deleteImConversationMembers");
throw new BusinessException("退出群聊错误");
}
// 遍历发送
......@@ -659,6 +736,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
/**
* 设置管理员
*
* @param param
* @return
*/
......@@ -687,6 +765,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
/**
* 群禁言
*
* @param param
* @return
*/
......@@ -704,11 +783,78 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
muteGroupParam.setMuted(param.getMutedType());
imConversationMapper.updateById(muteGroupParam);
deleteCacheImConversationById(param.getConversationId());
// 下发事件通知 开启、取消 群禁言
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.ne(ImConversationMembers::getFkClientId, currentClient.getId())
);
if (membersList.isEmpty()) {
throw new BusinessException("群聊成员列表为空");
}
// 保存事件消息
ImMessage imMessage = new ImMessage();
Map<String, Object> content = new HashMap<>();
content.put("operator", currentClient.getClientId());
imMessage.setContent(JsonUtils.encodeJson(content));
// 保存消息至消息表
imMessage.setId(SnowflakeUtil.getId());
Integer msgType = MutedEnum.NO.getCode().equals(param.getMutedType()) ?
MsgTypeEnum.CONVERSATION_MUTED_CANCEL.getUriCode()
: MsgTypeEnum.CONVERSATION_MUTED.getUriCode();
imMessage.setMsgType(msgType);
imMessage.setCreateTime(new Date());
imMessage.setFkAppid(currentClient.getFkAppid());
imMessage.setSender(currentClient.getId());
imMessage.setWithdraw(false);
imMessage.setEvent(true);
imMessage.setSystemFlag(false);
imMessage.setSendStatus(2);
imMessage.setFkConversationId(param.getConversationId());
imMessageService.save(imMessage);
for (ImConversationMembers member : membersList) {
// 不关心事件是否发送成功
try {
// 给所有成员下发事件消息
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getId, member.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
imMessageOnlineSend.setMsgId(imMessage.getId());
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setType(imMessage.getMsgType());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setContent(content);
imMessageOnlineSend.setConversationId(param.getConversationId());
imMessageOnlineSend.setWithdraw(Boolean.FALSE);
imMessageOnlineSend.setEvent(Boolean.TRUE);
// 向接收方推送
WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.CONVERSATION_EVENT_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(imMessageOnlineSend);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, imClientReceiver.getId());
} catch (Exception e) {
log.info("下发群禁言事件失败,接收人 {}", JSON.toJSONString(member));
}
}
return true;
}
@Override
public Boolean mutedGroupMember(MutedGroupParam param) {
public Boolean mutedGroupMember(MutedGroupMemberParam param) {
ImClient currentClient = imClientService.getCurrentClient();
if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
......@@ -733,6 +879,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
/**
* 判断当前操作人是否为指定角色成员
*
* @param currentClientId
* @param conversationId
* @return
......@@ -758,65 +905,43 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate imConversationNameUpdate) throws Exception {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
ImClient imClientSender = imClientService.getCurrentClient();
ImConversation imConversationById = imConversationService.getById(imConversationNameUpdate.getConversationId());
// 判断是否为群主
if (imConversationById == null || !imConversationById.getCreator().equals(imClientSender.getId())) {
return ApiResult.result(false);
public ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate param) {
ImClient currentClient = imClientService.getCurrentClient();
ImConversation imConversationById = imConversationService.getById(param.getConversationId());
if (!this.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
throw new BusinessException("操作人既不是群主也不是群管理员,无权限操作");
}
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, imConversationNameUpdate.getConversationId())
.notIn(ImConversationMembers::getId, imClientSender.getId())
.eq(ImConversationMembers::getFkConversationId, param.getConversationId())
.ne(ImConversationMembers::getFkClientId, currentClient.getId())
);
imConversationById.setName(imConversationNameUpdate.getName());
imConversationById.setName(param.getName());
boolean b = imConversationService.updateById(imConversationById);
// 删除redis中该会话的缓存
deleteCacheImConversationById(imConversationNameUpdate.getConversationId());
deleteCacheImConversationById(param.getConversationId());
if (b) {
// 下发群名称变动事件
// ws下发群属性变动事件
// 内容
HashMap<String, String> content = new HashMap<>();
HashMap<String, String> content = Maps.newHashMap();
content.put("name", imConversationById.getName());
// 遍历发送
for (ImConversationMembers conversationMembers : membersList) {
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getId, conversationMembers.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
// imMessageOnlineSend.setMsgId(null);
// imMessageOnlineSend.setSender(imClientSender.getClientId());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setType(MsgTypeEnum.CONVERSATION_NAME_CHANGE.getUriCode());
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setContent(content);
imMessageOnlineSend.setConversationId(conversationMembers.getFkConversationId());
// imMessageOnlineSend.setWithdraw(Boolean.FALSE);
imMessageOnlineSend.setEvent(Boolean.TRUE);
// 向接收方推送
......@@ -829,19 +954,15 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, imClientReceiver.getId());
}
return ApiResult.ok();
} else {
return ApiResult.fail();
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate) throws Exception {
public void saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate) {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
......@@ -861,7 +982,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkAppid, imApplication.getId())
.eq(ImConversationMembers::getFkConversationId, imConversationAttrUpdate.getConversationId())
.notIn(ImConversationMembers::getId, imClientSender.getId())
.ne(ImConversationMembers::getFkClientId, imClientSender.getId())
);
String attributes = JsonUtils.encodeJson(imConversationAttrUpdate.getAttributes());
......@@ -917,18 +1038,15 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
}
return ApiResult.ok();
} else {
return ApiResult.fail();
throw new BusinessException("修改错误");
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateImConversation(ImConversation imConversation) throws Exception {
public boolean updateImConversation(ImConversation imConversation) {
return super.updateById(imConversation);
}
......@@ -966,59 +1084,69 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
}
@Override
public Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam) throws Exception {
public Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam) {
Page<ImConversationQueryVo> page = new PageInfo<>(imConversationPageParam, OrderItem.desc(getLambdaColumn(ImConversation::getCreateTime)));
IPage<ImConversationQueryVo> iPage = imConversationMapper.getImConversationPageList(page, imConversationPageParam);
return new Paging<ImConversationQueryVo>(iPage);
}
@Override
public List<ConversationVo> getMyImConversationListAndMsgCount() throws Exception {
ImClient currentClient = imClientService.getCurrentClient();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> myImConversationListAndMsgCount = imConversationMapper.getMyImConversationListAndMsgCount(currentClient.getId(), null);
// 返回的
List<ConversationVo> myImConversationListAndMsgCountNew = new ArrayList<>();
// 转换json格式
for (ConversationVo myconversationlistvo : myImConversationListAndMsgCount) {
HashMap attributess = JsonUtils.json2Map(myconversationlistvo.getAttribute());
myconversationlistvo.setAttributes(attributess);
// 查询会话的最后一条消息
OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(myconversationlistvo.getId());
myconversationlistvo.setLastMsg(lastMsg);
myImConversationListAndMsgCountNew.add(myconversationlistvo);
public List<ConversationVo> getMyImConversationListAndMsgCount() {
try {
ImClient currentClient = imClientService.getCurrentClient();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> myImConversationListAndMsgCount = imConversationMapper.getMyImConversationListAndMsgCount(currentClient.getId(), currentClient.getClientId(), null);
// 返回的
List<ConversationVo> myImConversationListAndMsgCountNew = new ArrayList<>();
// 转换json格式
for (ConversationVo myconversationlistvo : myImConversationListAndMsgCount) {
HashMap attributess = JsonUtils.json2Map(myconversationlistvo.getAttribute());
myconversationlistvo.setAttributes(attributess);
// 查询会话的最后一条消息
OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(myconversationlistvo.getId());
myconversationlistvo.setLastMsg(lastMsg);
if (myconversationlistvo.getBeAtCount() > 0) {
myconversationlistvo.setIsBeAt(Boolean.TRUE);
}
myImConversationListAndMsgCountNew.add(myconversationlistvo);
}
return myImConversationListAndMsgCountNew;
} catch (Exception e) {
log.info("查询所有会话异常 ", e);
throw new BusinessException("查询错误,稍后重试");
}
return myImConversationListAndMsgCountNew;
}
@Override
public ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param) throws Exception {
ImClient client = imClientService.getCurrentClient();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> conversationList = imConversationMapper.getMyImConversationListAndMsgCount(client.getId(), param.getId());
if (CollectionUtils.isEmpty(conversationList)) {
return null;
public ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param) {
try {
ImClient client = imClientService.getCurrentClient();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> conversationList = imConversationMapper.getMyImConversationListAndMsgCount(client.getId(), client.getClientId(), param.getId());
if (CollectionUtils.isEmpty(conversationList)) {
return null;
}
ConversationVo conversationVo = conversationList.get(0);
HashMap attributess = JsonUtils.json2Map(conversationVo.getAttribute());
conversationVo.setAttributes(attributess);
// 查询会话的最后一条消息
OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(conversationVo.getId());
conversationVo.setLastMsg(lastMsg);
return conversationVo;
} catch (Exception e) {
log.info("添加或修改会话名称异常 ", e);
throw new BusinessException("修改会话名称错误");
}
ConversationVo conversationVo = conversationList.get(0);
HashMap attributess = JsonUtils.json2Map(conversationVo.getAttribute());
conversationVo.setAttributes(attributess);
// 查询会话的最后一条消息
OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(conversationVo.getId());
conversationVo.setLastMsg(lastMsg);
return conversationVo;
}
@Override
public List<ImConversation> getMyImConversationList() throws Exception {
public List<ImConversation> getMyImConversationList() {
ImClient client = imClientService.getCurrentClient();
return imConversationMapper.getMyImConversationList(client.getId());
}
......
......@@ -8,9 +8,11 @@ import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.ReadMsgStatusEnum;
import com.wecloud.im.mapper.ImInboxMapper;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
......@@ -154,12 +156,14 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
}
@Override
public Boolean updateMsgReadStatusByConversation(MsgReadStatusUpdateParam msgReadStatusUpdateParam) {
public Boolean updateMsgReadStatusByConversation(UpdateMsgReadStatusByConversationParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取该用户该会话所有未读消息 msgId 列表
List<ImInbox> imInboxList = this.list(new QueryWrapper<ImInbox>().lambda()
.eq(ImInbox::getFkConversationId, msgReadStatusUpdateParam.getConversationId())
.notIn(ImInbox::getReceiver, currentClient.getId()));
.eq(ImInbox::getFkConversationId, param.getConversationId())
.eq(ImInbox::getReadMsgStatus, ReadMsgStatusEnum.UNREAD.getCode())
.le(ImInbox::getFkMsgId, param.getMsgIdEnd())
.eq(ImInbox::getReceiver, currentClient.getId()));
if (CollectionUtils.isEmpty(imInboxList)) {
return true;
}
......@@ -178,36 +182,32 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
/**
* 下发状态类型消息
*
* @param curentClient 当前客户端
* @param currentClient 当前客户端
* @param msgTypeEnum 消息类型枚举
* @param contentMap 消息content内容
* @param msgIds 消息id集合
*/
private void sendMsgStatus(ImClient curentClient, MsgTypeEnum msgTypeEnum, HashMap<String, String> contentMap, List<Long> msgIds) {
private void sendMsgStatus(ImClient currentClient, MsgTypeEnum msgTypeEnum, HashMap<String, String> contentMap, List<Long> msgIds) {
// 遍历消息id集合
for (Long msgId : msgIds) {
// 查询该消息
ImMessage imMessageDb = imMessageService.getById(msgId);
// 根据会话id查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, imMessageDb.getFkConversationId())
.notIn(ImConversationMembers::getFkClientId, curentClient.getId())
.notIn(ImConversationMembers::getFkClientId, currentClient.getId())
);
// 遍历发送给该会话的每个成员
for (ImConversationMembers conversationMember : membersList) {
// 消息实体
ImMessage imMessage = new ImMessage();
imMessage.setId(msgId);
imMessage.setMsgType(msgTypeEnum.getUriCode());
imMessage.setCreateTime(new Date());
imMessage.setFkAppid(curentClient.getFkAppid());
imMessage.setSender(curentClient.getId());
imMessage.setFkAppid(currentClient.getFkAppid());
imMessage.setSender(currentClient.getId());
imMessage.setWithdraw(false);
imMessage.setEvent(true);
imMessage.setSystemFlag(false);
......@@ -220,12 +220,12 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
imMessageOnlineSend.setType(msgTypeEnum.getUriCode());
imMessageOnlineSend.setMsgId(imMessage.getId());
imMessageOnlineSend.setCreateTime(new Date());
imMessageOnlineSend.setSender(curentClient.getClientId());
imMessageOnlineSend.setSender(currentClient.getClientId());
imMessageOnlineSend.setContent(contentMap);
imMessageOnlineSend.setConversationId(conversationMember.getFkConversationId());
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, curentClient.getFkAppid())
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getId, conversationMember.getFkClientId()));
if (imClientReceiver == null) {
continue;
......
......@@ -38,7 +38,6 @@ import com.wecloud.im.vo.ReaderVo;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.model.request.PushVO;
import com.wecloud.im.ws.model.request.ReceiveDataVO;
import com.wecloud.im.ws.model.request.ReceiveVO;
import com.wecloud.im.ws.sender.ChannelSender;
......@@ -195,6 +194,7 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
imMessage.setSystemFlag(false);
imMessage.setSendStatus(2);
imMessage.setMsgType(data.getType());
imMessage.setAt(data.getAt());
imMessage.setFkConversationId(data.getToConversation());
this.save(imMessage);
return imMessage;
......@@ -487,10 +487,11 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
}
@Override
public Paging<OfflineMsgDto> getHistoryMsgConversationId(ImHistoryMessagePageParam imHistoryMessagePageParam) {
Page<ImMessage> page = new PageInfo<>(imHistoryMessagePageParam, OrderItem.desc(getLambdaColumn(ImMessage::getCreateTime)));
IPage<OfflineMsgDto> iPage = imMessageMapper.getHistoryMsgConversationId(page, imHistoryMessagePageParam);
public Paging<OfflineMsgDto> getHistoryMsgConversationId(ImHistoryMessagePageParam param) {
Page<ImMessage> page = new PageInfo<>(param, OrderItem.desc(getLambdaColumn(ImMessage::getCreateTime)));
ImClient currentClient = imClientService.getCurrentClient();
param.setCurrentFkClientId(currentClient.getId());
IPage<OfflineMsgDto> iPage = imMessageMapper.getHistoryMsgConversationId(page, param);
return new Paging<>(iPage);
}
......
......@@ -61,6 +61,9 @@ public class ConversationVo implements Serializable {
@ApiModelProperty("会话最后一条消息")
private OfflineMsgDto lastMsg;
@ApiModelProperty("是否被@ true-是 false-否")
private Boolean isBeAt;
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
......@@ -68,4 +71,7 @@ public class ConversationVo implements Serializable {
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer beAtCount;
}
......@@ -60,10 +60,10 @@ public class UserStateCacheManager extends UserStateListener {
public List<ClientChannelInfo> findOnlineInfosByClientId(Long clientId) {
// 获取所有 CLIENTS的 <platform>:<ip>
Set<String> platformAndIs = redisUtils.getForSetMembers(getUserStateCacheKey(clientId));
Set<String> platformAndIps = redisUtils.getForSetMembers(getUserStateCacheKey(clientId));
ArrayList<ClientChannelInfo> clientChannelInfos = new ArrayList<>();
for(String platformAndIp : platformAndIs) {
for(String platformAndIp : platformAndIps) {
String[] split = platformAndIp.split(RedisUtils.SPLIT);
ClientChannelInfo clientChannelInfo = new ClientChannelInfo();
clientChannelInfo.setPlatform(Integer.valueOf(split[0]));
......
......@@ -42,6 +42,18 @@ public enum MsgTypeEnum {
// 消息删除 -1017
MSG_DELETE(-1017),
// 解散群聊 -1018
CONVERSATION_DISBAND(-1018),
// 群聊禁言 -1019
CONVERSATION_MUTED(-1019),
// 群聊取消禁言 -1020
CONVERSATION_MUTED_CANCEL(-1020),
// 群成员备注修改 -1021
CONVERSATION_MEMBER_NAME_MODIFY(-1021),
;
private final int uriCode;
......
package com.wecloud.im.ws.enums;
/**
* @Author wenzhida
* @Date 2022/3/7 22:13
* @Description 多人音视频响应类型
*/
public enum WsMultiMeetResponseSubCmdEnum {
/**
* 邀请
*/
INVITE(1),
/**
* 拒接邀请
*/
REJECT(2),
/**
* 同意进入
*/
AGREE(3),
/**
* 主动离开
*/
LEAVE(4);
private final int cmdCode;
WsMultiMeetResponseSubCmdEnum(int cmdCode) {
this.cmdCode = cmdCode;
}
public int getCmdCode() {
return cmdCode;
}
}
......@@ -8,6 +8,11 @@ package com.wecloud.im.ws.enums;
public enum WsResponseCmdEnum {
/**
* 下发在线多人音视频事件
*/
MULTI_MEET_MSG(8),
/**
* 服务端下发通知型消息,例如:好友申请,好友认证结果.
* 参数值参考{@link com.wecloud.im.enums.EventResponseSubCmdEnum EventResponseSubCmdEnum}
*/
......
package com.wecloud.im.ws.sender;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.executor.SendMsgThreadPool;
import com.wecloud.utils.GetIpUtils;
import com.wecloud.im.router.RouterSendService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.im.ws.manager.ChannelManager;
......@@ -9,6 +9,7 @@ import com.wecloud.im.ws.model.ClientInfo;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.model.redis.ClientChannelInfo;
import com.wecloud.im.ws.model.request.ReceiveVO;
import com.wecloud.utils.GetIpUtils;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
......@@ -38,7 +39,11 @@ public class ChannelSender {
@Autowired
private UserStateCacheManager userStateCacheManager;
@DubboReference(parameters = {"router", "address"})
/*
* 指定ip调用,router=address;
* injvm = false要设置成false,否则会调用到本地提供者
*/
@DubboReference(injvm = false, interfaceClass = RouterSendService.class, parameters = {"router", "address"})
private RouterSendService routerSendService;
/**
......@@ -104,6 +109,8 @@ public class ChannelSender {
batchSendMsgLocal(toClientIdAndPlatforms, msgJson);
} else {
String msgJson = JsonUtils.encodeJson(responseModel);
// dubbo指定ip调用
Address address = new Address(toIp, 20881);
RpcContext.getContext().setObjectAttachment("address", address);
routerSendService.batchSendMsgRemote(toClientIdAndPlatforms, msgJson);
......@@ -139,8 +146,10 @@ public class ChannelSender {
// RpcContext.getContext().set("ip", channelInfo.getLanIp());
// 根据provider的ip,port创建Address实例
for(ClientChannelInfo clientChannelInfo : channelInfoEntry.getValue()) {
// dubbo指定ip调用
Address address = new Address(clientChannelInfo.getLanIp(), 20881);
RpcContext.getContext().setObjectAttachment("address", address);
log.info("dubbo指定ip调用 {}", JSON.toJSONString(address));
routerSendService.sendMsgRemote(toClientId, clientChannelInfo.getPlatform(), msgJson);
}
}
......
package com.wecloud.multimeet.entity.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:21
* @Description 同意进入多人音视频
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MultiMeetAgreeResponse extends MultiMeetDataBase implements Serializable {
private static final long serialVersionUID = 1623214002231302888L;
/**
* 会话id
*/
private Long conversationId;
/**
* 房间id
*/
private String roomId;
/**
* 发起会议人clientId
*/
private String inviterClientId;
}
package com.wecloud.multimeet.entity.response;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:01
* @Description 多人音视频会议长连接响应基类
*/
@Data
public class MultiMeetDataBase implements Serializable {
private static final long serialVersionUID = -4151469100462562164L;
/**
* 子指令
*/
private Integer subCmd;
private String clientId;
private Long timestamp;
}
package com.wecloud.multimeet.entity.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:02
* @Description 邀请加入多人音视频会议
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MultiMeetInviteResponse extends MultiMeetDataBase implements Serializable {
/**
* 会话id
*/
private Long conversationId;
/**
* 房间id
*/
private String roomId;
}
package com.wecloud.multimeet.entity.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:21
* @Description 主动离开多人音视频
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MultiMeetLeaveResponse extends MultiMeetDataBase implements Serializable {
private static final long serialVersionUID = 734428267643207411L;
/**
* 会话id
*/
private Long conversationId;
/**
* 房间id
*/
private String roomId;
/**
* 发起会议人clientId
*/
private String inviterClientId;
}
package com.wecloud.multimeet.entity.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/7 22:21
* @Description 拒绝进入多人音视频
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MultiMeetRejectResponse extends MultiMeetDataBase implements Serializable {
/**
* 会话id
*/
private Long conversationId;
/**
* 房间id
*/
private String roomId;
/**
* 发起会议人clientId
*/
private String inviterClientId;
}
package com.wecloud.multimeet.service;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
/**
* @Author wenzhida
* @Date 2022/3/7 18:26
* @Description 多人音视频服务接口
*/
public interface MultiMeetService {
/**
* 发起多人音视频邀请
* @param param
* @return
*/
void invite(InviteToMultiMeetParam param);
/**
* 拒接加入会议
* @param param
*/
void reject(RejectToMultiMeetParam param);
/**
* 同意进入会议
* @param param
*/
void agree(AgreeToMultiMeetParam param);
/**
* 同意进入会议
* @param param
*/
void leave(LeaveFromMultiMeetParam param);
}
package com.wecloud.multimeet.service;
import com.wecloud.multimeet.entity.response.MultiMeetAgreeResponse;
import com.wecloud.multimeet.entity.response.MultiMeetInviteResponse;
import com.wecloud.multimeet.entity.response.MultiMeetLeaveResponse;
import com.wecloud.multimeet.entity.response.MultiMeetRejectResponse;
/**
* @Author wenzhida
* @Date 2022/3/7 21:47
* @Description 多人音视频 webSocket下发指令数据
*/
public interface WsMultiMeetWrite {
/**
* 发送邀请
* @param multiMeetInviteResponse
* @param toFkClientId
*/
void invite(MultiMeetInviteResponse multiMeetInviteResponse, Long toFkClientId);
/**
* 拒接邀请
* @param multiMeetRejectResponse
* @param toFkClientId
*/
void reject(MultiMeetRejectResponse multiMeetRejectResponse, Long toFkClientId);
/**
* 同意进入会议
* @param multiMeetAgreeResponse
* @param toFkClientId
*/
void agree(MultiMeetAgreeResponse multiMeetAgreeResponse, Long toFkClientId);
/**
* 主动离开会议
* @param multiMeetLeaveResponse
* @param toFkClientId
*/
void leave(MultiMeetLeaveResponse multiMeetLeaveResponse, Long toFkClientId);
}
package com.wecloud.multimeet.service.impl;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.multimeet.entity.response.MultiMeetAgreeResponse;
import com.wecloud.multimeet.entity.response.MultiMeetInviteResponse;
import com.wecloud.multimeet.entity.response.MultiMeetLeaveResponse;
import com.wecloud.multimeet.entity.response.MultiMeetRejectResponse;
import com.wecloud.multimeet.service.MultiMeetService;
import com.wecloud.multimeet.service.WsMultiMeetWrite;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author wenzhida
* @Date 2022/3/7 18:43
* @Description 多人音视频接口实现
*/
@Slf4j
@Service
public class MultiMeetServiceImpl implements MultiMeetService {
@Autowired
private WsMultiMeetWrite wsMultiMeetWrite;
@Autowired
private ImClientService imClientService;
@Autowired
private UserStateCacheManager userStateCacheManager;
@Override
public void invite(InviteToMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 判断发起方必须在线
boolean onlineStatus = userStateCacheManager.isOnline(currentClient.getId());
if (!onlineStatus) {
log.info("发起方必须在线" + currentClient.getFkAppid() + currentClient.getClientId());
throw new BusinessException("发起方必须在线");
}
for (String toClient : param.getToClients()) {
ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), toClient);
if (receiver == null) {
log.info("查无接收人信息 {}", toClient);
continue;
}
// ws向接收方发送通知
MultiMeetInviteResponse multiMeetInviteResponse = new MultiMeetInviteResponse();
multiMeetInviteResponse.setConversationId(param.getConversationId());
multiMeetInviteResponse.setRoomId(param.getRoomId());
multiMeetInviteResponse.setClientId(currentClient.getClientId());
multiMeetInviteResponse.setTimestamp(System.currentTimeMillis());
wsMultiMeetWrite.invite(multiMeetInviteResponse, receiver.getId());
// TODO 待开发 下发安卓和ios系统推送
}
}
@Override
public void reject(RejectToMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// ws向接收方发送通知
MultiMeetRejectResponse multiMeetRejectResponse = new MultiMeetRejectResponse();
multiMeetRejectResponse.setConversationId(param.getConversationId());
multiMeetRejectResponse.setRoomId(param.getRoomId());
multiMeetRejectResponse.setClientId(currentClient.getClientId());
multiMeetRejectResponse.setTimestamp(System.currentTimeMillis());
ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
if (receiver == null) {
log.info("查无接收人信息 {}", param.getInviterClientId());
throw new BusinessException("查无发起会议人信息");
}
wsMultiMeetWrite.reject(multiMeetRejectResponse, receiver.getId());
}
@Override
public void agree(AgreeToMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// ws向接收方发送通知
MultiMeetAgreeResponse multiMeetAgreeResponse = new MultiMeetAgreeResponse();
multiMeetAgreeResponse.setConversationId(param.getConversationId());
multiMeetAgreeResponse.setRoomId(param.getRoomId());
multiMeetAgreeResponse.setClientId(currentClient.getClientId());
multiMeetAgreeResponse.setTimestamp(System.currentTimeMillis());
ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
if (receiver == null) {
log.info("查无接收人信息 {}", param.getInviterClientId());
throw new BusinessException("查无发起会议人信息");
}
wsMultiMeetWrite.agree(multiMeetAgreeResponse, receiver.getId());
}
@Override
public void leave(LeaveFromMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// ws向接收方发送通知
MultiMeetLeaveResponse multiMeetLeaveResponse = new MultiMeetLeaveResponse();
multiMeetLeaveResponse.setConversationId(param.getConversationId());
multiMeetLeaveResponse.setRoomId(param.getRoomId());
multiMeetLeaveResponse.setClientId(currentClient.getClientId());
multiMeetLeaveResponse.setTimestamp(System.currentTimeMillis());
ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
if (receiver == null) {
log.info("查无接收人信息 {}", param.getInviterClientId());
throw new BusinessException("查无发起会议人信息");
}
wsMultiMeetWrite.leave(multiMeetLeaveResponse, receiver.getId());
}
}
package com.wecloud.multimeet.service.impl;
import com.wecloud.im.ws.enums.WsMultiMeetResponseSubCmdEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.multimeet.entity.response.MultiMeetAgreeResponse;
import com.wecloud.multimeet.entity.response.MultiMeetInviteResponse;
import com.wecloud.multimeet.entity.response.MultiMeetLeaveResponse;
import com.wecloud.multimeet.entity.response.MultiMeetRejectResponse;
import com.wecloud.multimeet.service.WsMultiMeetWrite;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author wenzhida
* @Date 2022/3/7 22:26
* @Description 多人音视频长连接下发
*/
@Service
public class WsMultiMeetWriteImpl implements WsMultiMeetWrite {
@Autowired
private ChannelSender channelSender;
@Override
public void invite(MultiMeetInviteResponse multiMeetInviteResponse, Long toFkClientId) {
multiMeetInviteResponse.setSubCmd(WsMultiMeetResponseSubCmdEnum.INVITE.getCmdCode());
// 向接收方推送
WsResponse<MultiMeetInviteResponse> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.MULTI_MEET_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(multiMeetInviteResponse);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, toFkClientId);
}
@Override
public void reject(MultiMeetRejectResponse multiMeetRejectResponse, Long toFkClientId) {
multiMeetRejectResponse.setSubCmd(WsMultiMeetResponseSubCmdEnum.REJECT.getCmdCode());
// 向接收方推送
WsResponse<MultiMeetRejectResponse> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.MULTI_MEET_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(multiMeetRejectResponse);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, toFkClientId);
}
@Override
public void agree(MultiMeetAgreeResponse multiMeetAgreeResponse, Long toFkClientId) {
multiMeetAgreeResponse.setSubCmd(WsMultiMeetResponseSubCmdEnum.AGREE.getCmdCode());
// 向接收方推送
WsResponse<MultiMeetAgreeResponse> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.MULTI_MEET_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(multiMeetAgreeResponse);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, toFkClientId);
}
@Override
public void leave(MultiMeetLeaveResponse multiMeetLeaveResponse, Long toFkClientId) {
multiMeetLeaveResponse.setSubCmd(WsMultiMeetResponseSubCmdEnum.LEAVE.getCmdCode());
// 向接收方推送
WsResponse<MultiMeetLeaveResponse> responseModel = new WsResponse<>();
responseModel.setCmd(WsResponseCmdEnum.MULTI_MEET_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(multiMeetLeaveResponse);
responseModel.setReqId(null);
channelSender.sendMsg(responseModel, toFkClientId);
}
}
......@@ -43,7 +43,7 @@ public interface MangerRtcCacheService {
* @param clientId
* @param rtcChannelId 雪花算法生成频道id
*/
void create(Long clientId, Long toClientId, Long rtcChannelId) throws JsonProcessingException;
void create(Long clientId, Long toClientId, Long rtcChannelId);
/**
* 加入频道
......
......@@ -18,7 +18,7 @@ public interface RtcService {
/**
* 创建一个频道,并向接收方发送系统推送
*/
ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam) throws JsonProcessingException;
ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam);
/**
* 加入频道
......
......@@ -11,6 +11,7 @@ import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.im.ws.cache.UserStateListener;
......@@ -25,6 +26,7 @@ import com.wecloud.rtc.service.RtcService;
import com.wecloud.rtc.service.WsRtcWrite;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -54,6 +56,9 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
@Autowired
private UserStateCacheManager userStateCacheManager;
@Autowired
private ImClientBlacklistService imClientBlacklistService;
@Override
public void onLineEvent(Long client, Integer platform, String longChannelId) {
// nothing need to do
......@@ -77,7 +82,7 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
}
@Override
public ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam) throws JsonProcessingException {
public ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam) {
ImClient currentClient = imClientService.getCurrentClient();
Long rtcChannelId = SnowflakeUtil.getId();
// 判断发起方必须在线
......@@ -90,6 +95,8 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
if (toClient == null) {
ApiResult.fail();
}
// 拉黑逻辑
black(currentClient, toClient);
// 添加缓存
mangerRtcCacheService.create(currentClient.getId(), toClient.getId(), rtcChannelId);
......@@ -286,4 +293,25 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
return ApiResult.ok(true);
}
/**
* 判断是否被拉黑
*
* @param currentClient
* @param toClient
* @return
*/
private void black(ImClient currentClient, ImClient toClient) {
// 判断是否被拉黑
boolean beBlack = imClientBlacklistService.isBeBlack(toClient.getClientId(), currentClient.getClientId());
if (beBlack) {
throw new BusinessException("被对方拉黑了");
}
// 是否把对方拉黑
boolean black = imClientBlacklistService.isBeBlack(currentClient.getClientId(), toClient.getClientId());
if (black) {
throw new BusinessException("你把对方拉黑了");
}
}
}
......@@ -17,16 +17,9 @@
<select id="getImClientBlacklistPageList" resultType="com.wecloud.im.param.ImClientBlacklistQueryVo">
SELECT im_client.client_id AS clientIdBePrevent
FROM im_client_blacklist
INNER JOIN im_client ON im_client.id = im_client_blacklist.client_id_be_prevent
INNER JOIN im_client ON im_client.client_id = im_client_blacklist.client_id_be_prevent
WHERE im_client_blacklist.client_id_prevent = #{clientId}
ORDER BY im_client_blacklist.create_time DESC
</select>
<!-- <select id="getImClientBlacklistPageList" parameterType="com.wecloud.im.param.ImClientBlacklistPageParam"-->
<!-- resultType="com.wecloud.im.param.ImClientBlacklistQueryVo">-->
<!-- select-->
<!-- <include refid="Base_Column_List"/>-->
<!-- from im_client_blacklist-->
<!-- </select>-->
</mapper>
......@@ -36,6 +36,12 @@
WHERE im_inbox.fk_conversation_id = imConversation.id
AND im_inbox.receiver = #{currentClientId}
AND im_inbox.read_msg_status = 0) AS msg_not_read_count,
(SELECT COUNT(*)
FROM im_inbox INNER JOIN im_message ON im_inbox.fk_msg_id = im_message.id
WHERE im_inbox.fk_conversation_id = imConversation.id
AND im_inbox.receiver = #{currentClientId}
AND im_inbox.read_msg_status = 0
AND (FIND_IN_SET(#{clientId},im_message.`at`) > 0 or FIND_IN_SET('-1',im_message.`at`) > 0)) AS beAtCount,
(
SELECT GROUP_CONCAT(im_client.client_id)
FROM im_conversation_members AS im_conversation_members
......
......@@ -74,5 +74,9 @@
#{fkClientId}
</foreach>
</update>
<delete id="deleteByConversationId">
DELETE FROM im_conversation_members WHERE fk_conversation_id = #{conversationId}
</delete>
</mapper>
......@@ -73,6 +73,7 @@
FROM `im_message`
INNER JOIN `im_client` ON `im_client`.id = `im_message`.sender
WHERE fk_conversation_id = #{param.conversationId} and im_message.is_delete = 1 and im_message.withdraw = 0
and (im_message.`event`=0 || (im_message.`event`=1 and sender != #{param.currentFkClientId} ))
<if test="param.msgIdStart != null">
AND im_message.id > #{param.msgIdStart}
</if>
......
......@@ -136,6 +136,12 @@ public enum ApiCode {
* 已被禁言
*/
IS_BE_MUTED(6015, "api.response.code.IS_BE_MUTED"),
/**
* 群聊已解散
*/
IS_BE_DISBAND(6016, "api.response.code.IS_BE_DISBAND"),
;
private final int code;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment