first commit
This commit is contained in:
0
l-im-master/l-im/im-service/im-service.iml
Normal file
0
l-im-master/l-im/im-service/im-service.iml
Normal file
101
l-im-master/l-im/im-service/pom.xml
Normal file
101
l-im-master/l-im/im-service/pom.xml
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>im-system</artifactId>
|
||||
<groupId>com.lld</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<description>lld-im-service project</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<artifactId>service</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- rabbitmq -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.sgroschupf</groupId>
|
||||
<artifactId>zkclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- spring boot web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.lld</groupId>
|
||||
<artifactId>codec</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--MySQL JDBC驱动 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--MySQL -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.jeffreyning</groupId>
|
||||
<artifactId>mybatisplus-plus</artifactId>
|
||||
<version>1.5.1-RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- common -->
|
||||
<dependency>
|
||||
<groupId>com.lld</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lld.im.service;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.lld.im.service",
|
||||
"com.lld.im.common"})
|
||||
@MapperScan("com.lld.im.service.*.dao.mapper")
|
||||
//导入用户资料,删除用户资料,修改用户资料,查询用户资料
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.lld.im.service.config;
|
||||
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.enums.ImUrlRouteWayEnum;
|
||||
import com.lld.im.common.enums.RouteHashMethodEnum;
|
||||
import com.lld.im.common.route.RouteHandle;
|
||||
import com.lld.im.common.route.algorithm.consistenthash.AbstractConsistentHash;
|
||||
import com.lld.im.common.route.algorithm.consistenthash.ConsistentHashHandle;
|
||||
import com.lld.im.common.route.algorithm.consistenthash.TreeMapConsistentHash;
|
||||
import com.lld.im.common.route.algorithm.loop.LoopHandle;
|
||||
import com.lld.im.common.route.algorithm.random.RandomHandle;
|
||||
import com.lld.im.service.utils.SnowflakeIdWorker;
|
||||
import org.I0Itec.zkclient.ZkClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Configuration
|
||||
public class BeanConfig {
|
||||
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Bean
|
||||
public ZkClient buildZKClient() {
|
||||
return new ZkClient(appConfig.getZkAddr(),
|
||||
appConfig.getZkConnectTimeOut());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteHandle routeHandle() throws Exception {
|
||||
|
||||
Integer imRouteWay = appConfig.getImRouteWay();
|
||||
String routWay = "";
|
||||
|
||||
ImUrlRouteWayEnum handler = ImUrlRouteWayEnum.getHandler(imRouteWay);
|
||||
routWay = handler.getClazz();
|
||||
|
||||
RouteHandle routeHandle = (RouteHandle) Class.forName(routWay).newInstance();
|
||||
if(handler == ImUrlRouteWayEnum.HASH){
|
||||
|
||||
Method setHash = Class.forName(routWay).getMethod("setHash", AbstractConsistentHash.class);
|
||||
Integer consistentHashWay = appConfig.getConsistentHashWay();
|
||||
String hashWay = "";
|
||||
|
||||
RouteHashMethodEnum hashHandler = RouteHashMethodEnum.getHandler(consistentHashWay);
|
||||
hashWay = hashHandler.getClazz();
|
||||
AbstractConsistentHash consistentHash
|
||||
= (AbstractConsistentHash) Class.forName(hashWay).newInstance();
|
||||
setHash.invoke(routeHandle,consistentHash);
|
||||
}
|
||||
|
||||
return routeHandle;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EasySqlInjector easySqlInjector () {
|
||||
return new EasySqlInjector();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SnowflakeIdWorker buildSnowflakeSeq() throws Exception {
|
||||
return new SnowflakeIdWorker(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lld.im.service.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EasySqlInjector extends DefaultSqlInjector {
|
||||
@Override
|
||||
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
|
||||
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
|
||||
methodList.add(new InsertBatchSomeColumn()); // 添加InsertBatchSomeColumn方法
|
||||
return methodList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.lld.im.service.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Autowired
|
||||
RedisConnectionFactory redisConnectionFactory;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<Object, Object> redisTemplate() {
|
||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
|
||||
//Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
//使用Fastjson2JsonRedisSerializer来序列化和反序列化redis的value值 by zhengkai
|
||||
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
serializer.setObjectMapper(mapper);
|
||||
|
||||
template.setValueSerializer(new StringRedisSerializer());
|
||||
//使用StringRedisSerializer来序列化和反序列化redis的key值
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.afterPropertiesSet();
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
template.setHashValueSerializer(serializer);
|
||||
|
||||
return template;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.lld.im.service.config;
|
||||
|
||||
import com.lld.im.service.interceptor.GateWayInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
GateWayInterceptor gateWayInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(gateWayInterceptor)
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns("/v1/user/login")
|
||||
.excludePathPatterns("/v1/message/checkSend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.allowCredentials(true)
|
||||
.maxAge(3600)
|
||||
.allowedHeaders("*");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.lld.im.service.conversation.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.service.conversation.model.DeleteConversationReq;
|
||||
import com.lld.im.service.conversation.model.UpdateConversationReq;
|
||||
import com.lld.im.service.conversation.service.ConversationService;
|
||||
import com.lld.im.service.group.model.req.ImportGroupReq;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("v1/conversation")
|
||||
public class ConversationController {
|
||||
|
||||
@Autowired
|
||||
ConversationService conversationService;
|
||||
|
||||
@RequestMapping("/deleteConversation")
|
||||
public ResponseVO deleteConversation(@RequestBody @Validated DeleteConversationReq
|
||||
req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
// req.setOperater(identifier);
|
||||
return conversationService.deleteConversation(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/updateConversation")
|
||||
public ResponseVO updateConversation(@RequestBody @Validated UpdateConversationReq
|
||||
req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
// req.setOperater(identifier);
|
||||
return conversationService.updateConversation(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/syncConversationList")
|
||||
public ResponseVO syncFriendShipList(@RequestBody @Validated SyncReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return conversationService.syncConversationSet(req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.lld.im.service.conversation.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
@TableName("im_conversation_set")
|
||||
public class ImConversationSetEntity {
|
||||
|
||||
//会话id 0_fromId_toId
|
||||
private String conversationId;
|
||||
|
||||
//会话类型
|
||||
private Integer conversationType;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
|
||||
private int isMute;
|
||||
|
||||
private int isTop;
|
||||
|
||||
private Long sequence;
|
||||
|
||||
private Long readedSequence;
|
||||
|
||||
private Integer appId;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lld.im.service.conversation.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.conversation.dao.ImConversationSetEntity;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Repository
|
||||
public interface ImConversationSetMapper extends BaseMapper<ImConversationSetEntity> {
|
||||
|
||||
@Update(" update im_conversation_set set readed_sequence = #{readedSequence},sequence = #{sequence} " +
|
||||
" where conversation_id = #{conversationId} and app_id = #{appId} AND readed_sequence < #{readedSequence}")
|
||||
public void readMark(ImConversationSetEntity imConversationSetEntity);
|
||||
|
||||
@Select(" select max(sequence) from im_conversation_set where app_id = #{appId} AND from_id = #{userId} ")
|
||||
Long geConversationSetMaxSeq(Integer appId, String userId);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lld.im.service.conversation.model;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class DeleteConversationReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "会话id不能为空")
|
||||
private String conversationId;
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lld.im.service.conversation.model;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class UpdateConversationReq extends RequestBase {
|
||||
|
||||
private String conversationId;
|
||||
|
||||
private Integer isMute;
|
||||
|
||||
private Integer isTop;
|
||||
|
||||
private String fromId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.lld.im.service.conversation.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.lld.im.codec.pack.conversation.DeleteConversationPack;
|
||||
import com.lld.im.codec.pack.conversation.UpdateConversationPack;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.ConversationErrorCode;
|
||||
import com.lld.im.common.enums.ConversationTypeEnum;
|
||||
import com.lld.im.common.enums.command.ConversationEventCommand;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.common.model.SyncResp;
|
||||
import com.lld.im.common.model.message.MessageReadedContent;
|
||||
import com.lld.im.service.conversation.dao.ImConversationSetEntity;
|
||||
import com.lld.im.service.conversation.dao.mapper.ImConversationSetMapper;
|
||||
import com.lld.im.service.conversation.model.DeleteConversationReq;
|
||||
import com.lld.im.service.conversation.model.UpdateConversationReq;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipEntity;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import com.lld.im.service.utils.WriteUserSeq;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class ConversationService {
|
||||
|
||||
@Autowired
|
||||
ImConversationSetMapper imConversationSetMapper;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
@Autowired
|
||||
WriteUserSeq writeUserSeq;
|
||||
|
||||
public String convertConversationId(Integer type,String fromId,String toId){
|
||||
return type + "_" + fromId + "_" + toId;
|
||||
}
|
||||
|
||||
public void messageMarkRead(MessageReadedContent messageReadedContent){
|
||||
|
||||
String toId = messageReadedContent.getToId();
|
||||
if(messageReadedContent.getConversationType() == ConversationTypeEnum.GROUP.getCode()){
|
||||
toId = messageReadedContent.getGroupId();
|
||||
}
|
||||
String conversationId = convertConversationId(messageReadedContent.getConversationType(),
|
||||
messageReadedContent.getFromId(), toId);
|
||||
QueryWrapper<ImConversationSetEntity> query = new QueryWrapper<>();
|
||||
query.eq("conversation_id",conversationId);
|
||||
query.eq("app_id",messageReadedContent.getAppId());
|
||||
ImConversationSetEntity imConversationSetEntity = imConversationSetMapper.selectOne(query);
|
||||
if(imConversationSetEntity == null){
|
||||
imConversationSetEntity = new ImConversationSetEntity();
|
||||
long seq = redisSeq.doGetSeq(messageReadedContent.getAppId() + ":" + Constants.SeqConstants.Conversation);
|
||||
imConversationSetEntity.setConversationId(conversationId);
|
||||
BeanUtils.copyProperties(messageReadedContent,imConversationSetEntity);
|
||||
imConversationSetEntity.setReadedSequence(messageReadedContent.getMessageSequence());
|
||||
imConversationSetEntity.setToId(toId);
|
||||
imConversationSetEntity.setSequence(seq);
|
||||
imConversationSetMapper.insert(imConversationSetEntity);
|
||||
writeUserSeq.writeUserSeq(messageReadedContent.getAppId(),
|
||||
messageReadedContent.getFromId(),Constants.SeqConstants.Conversation,seq);
|
||||
}else{
|
||||
long seq = redisSeq.doGetSeq(messageReadedContent.getAppId() + ":" + Constants.SeqConstants.Conversation);
|
||||
imConversationSetEntity.setSequence(seq);
|
||||
imConversationSetEntity.setReadedSequence(messageReadedContent.getMessageSequence());
|
||||
imConversationSetMapper.readMark(imConversationSetEntity);
|
||||
writeUserSeq.writeUserSeq(messageReadedContent.getAppId(),
|
||||
messageReadedContent.getFromId(),Constants.SeqConstants.Conversation,seq);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 删除会话
|
||||
* @param
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @author lld
|
||||
*/
|
||||
public ResponseVO deleteConversation(DeleteConversationReq req){
|
||||
|
||||
//置顶 有免打扰
|
||||
// QueryWrapper<ImConversationSetEntity> queryWrapper = new QueryWrapper<>();
|
||||
// queryWrapper.eq("conversation_id",req.getConversationId());
|
||||
// queryWrapper.eq("app_id",req.getAppId());
|
||||
// ImConversationSetEntity imConversationSetEntity = imConversationSetMapper.selectOne(queryWrapper);
|
||||
// if(imConversationSetEntity != null){
|
||||
// imConversationSetEntity.setIsMute(0);
|
||||
// imConversationSetEntity.setIsTop(0);
|
||||
// imConversationSetMapper.update(imConversationSetEntity,queryWrapper);
|
||||
// }
|
||||
|
||||
if(appConfig.getDeleteConversationSyncMode() == 1){
|
||||
DeleteConversationPack pack = new DeleteConversationPack();
|
||||
pack.setConversationId(req.getConversationId());
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(),
|
||||
ConversationEventCommand.CONVERSATION_DELETE,
|
||||
pack,new ClientInfo(req.getAppId(),req.getClientType(),
|
||||
req.getImei()));
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 更新会话 置顶or免打扰
|
||||
* @param
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @author lld
|
||||
*/
|
||||
public ResponseVO updateConversation(UpdateConversationReq req){
|
||||
|
||||
|
||||
|
||||
|
||||
if(req.getIsTop() == null && req.getIsMute() == null){
|
||||
return ResponseVO.errorResponse(ConversationErrorCode.CONVERSATION_UPDATE_PARAM_ERROR);
|
||||
}
|
||||
QueryWrapper<ImConversationSetEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("conversation_id",req.getConversationId());
|
||||
queryWrapper.eq("app_id",req.getAppId());
|
||||
ImConversationSetEntity imConversationSetEntity = imConversationSetMapper.selectOne(queryWrapper);
|
||||
if(imConversationSetEntity != null){
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Conversation);
|
||||
|
||||
if(req.getIsMute() != null){
|
||||
imConversationSetEntity.setIsTop(req.getIsTop());
|
||||
}
|
||||
if(req.getIsMute() != null){
|
||||
imConversationSetEntity.setIsMute(req.getIsMute());
|
||||
}
|
||||
imConversationSetEntity.setSequence(seq);
|
||||
imConversationSetMapper.update(imConversationSetEntity,queryWrapper);
|
||||
writeUserSeq.writeUserSeq(req.getAppId(), req.getFromId(),
|
||||
Constants.SeqConstants.Conversation, seq);
|
||||
|
||||
UpdateConversationPack pack = new UpdateConversationPack();
|
||||
pack.setConversationId(req.getConversationId());
|
||||
pack.setIsMute(imConversationSetEntity.getIsMute());
|
||||
pack.setIsTop(imConversationSetEntity.getIsTop());
|
||||
pack.setSequence(seq);
|
||||
pack.setConversationType(imConversationSetEntity.getConversationType());
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(),
|
||||
ConversationEventCommand.CONVERSATION_UPDATE,
|
||||
pack,new ClientInfo(req.getAppId(),req.getClientType(),
|
||||
req.getImei()));
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
public ResponseVO syncConversationSet(SyncReq req) {
|
||||
if(req.getMaxLimit() > 100){
|
||||
req.setMaxLimit(100);
|
||||
}
|
||||
|
||||
SyncResp<ImConversationSetEntity> resp = new SyncResp<>();
|
||||
//seq > req.getseq limit maxLimit
|
||||
QueryWrapper<ImConversationSetEntity> queryWrapper =
|
||||
new QueryWrapper<>();
|
||||
queryWrapper.eq("from_id",req.getOperater());
|
||||
queryWrapper.gt("sequence",req.getLastSequence());
|
||||
queryWrapper.eq("app_id",req.getAppId());
|
||||
queryWrapper.last(" limit " + req.getMaxLimit());
|
||||
queryWrapper.orderByAsc("sequence");
|
||||
List<ImConversationSetEntity> list = imConversationSetMapper
|
||||
.selectList(queryWrapper);
|
||||
|
||||
if(!CollectionUtils.isEmpty(list)){
|
||||
ImConversationSetEntity maxSeqEntity = list.get(list.size() - 1);
|
||||
resp.setDataList(list);
|
||||
//设置最大seq
|
||||
Long friendShipMaxSeq = imConversationSetMapper.geConversationSetMaxSeq(req.getAppId(), req.getOperater());
|
||||
resp.setMaxSequence(friendShipMaxSeq);
|
||||
//设置是否拉取完毕
|
||||
resp.setCompleted(maxSeqEntity.getSequence() >= friendShipMaxSeq);
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
resp.setCompleted(true);
|
||||
return ResponseVO.successResponse(resp);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.lld.im.service.exception;
|
||||
|
||||
import com.lld.im.common.BaseErrorCode;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.exception.ApplicationException;
|
||||
import org.hibernate.validator.internal.engine.path.PathImpl;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.Set;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
|
||||
@ExceptionHandler(value=Exception.class)
|
||||
@ResponseBody
|
||||
public ResponseVO unknowException(Exception e){
|
||||
e.printStackTrace();
|
||||
ResponseVO resultBean =new ResponseVO();
|
||||
resultBean.setCode(BaseErrorCode.SYSTEM_ERROR.getCode());
|
||||
resultBean.setMsg(BaseErrorCode.SYSTEM_ERROR.getError());
|
||||
/**
|
||||
* 未知异常的话,这里写逻辑,发邮件,发短信都可以、、
|
||||
*/
|
||||
return resultBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validator 参数校验异常处理
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = ConstraintViolationException.class)
|
||||
@ResponseBody
|
||||
public Object handleMethodArgumentNotValidException(ConstraintViolationException ex) {
|
||||
|
||||
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
|
||||
ResponseVO resultBean =new ResponseVO();
|
||||
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
|
||||
for (ConstraintViolation<?> constraintViolation : constraintViolations) {
|
||||
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath();
|
||||
// 读取参数字段,constraintViolation.getMessage() 读取验证注解中的message值
|
||||
String paramName = pathImpl.getLeafNode().getName();
|
||||
String message = "参数{".concat(paramName).concat("}").concat(constraintViolation.getMessage());
|
||||
resultBean.setMsg(message);
|
||||
|
||||
return resultBean;
|
||||
}
|
||||
resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + ex.getMessage());
|
||||
return resultBean;
|
||||
}
|
||||
|
||||
@ExceptionHandler(ApplicationException.class)
|
||||
@ResponseBody
|
||||
public Object applicationExceptionHandler(ApplicationException e) {
|
||||
// 使用公共的结果类封装返回结果, 这里我指定状态码为
|
||||
ResponseVO resultBean =new ResponseVO();
|
||||
resultBean.setCode(e.getCode());
|
||||
resultBean.setMsg(e.getError());
|
||||
return resultBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validator 参数校验异常处理
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = BindException.class)
|
||||
@ResponseBody
|
||||
public Object handleException2(BindException ex) {
|
||||
FieldError err = ex.getFieldError();
|
||||
String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage());
|
||||
ResponseVO resultBean =new ResponseVO();
|
||||
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
|
||||
resultBean.setMsg(message);
|
||||
return resultBean;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//json格式
|
||||
@ExceptionHandler(value = MethodArgumentNotValidException.class)
|
||||
@ResponseBody
|
||||
public Object handleException1(MethodArgumentNotValidException ex) {
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
BindingResult re = ex.getBindingResult();
|
||||
for (ObjectError error : re.getAllErrors()) {
|
||||
errorMsg.append(error.getDefaultMessage()).append(",");
|
||||
}
|
||||
errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
|
||||
|
||||
ResponseVO resultBean =new ResponseVO();
|
||||
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
|
||||
resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + " : " + errorMsg.toString());
|
||||
return resultBean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.lld.im.service.friendship.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.service.friendship.model.req.*;
|
||||
import com.lld.im.service.friendship.service.ImFriendService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("v1/friendship")
|
||||
public class ImFriendShipController {
|
||||
|
||||
@Autowired
|
||||
ImFriendService imFriendShipService;
|
||||
|
||||
@RequestMapping("/importFriendShip")
|
||||
public ResponseVO importFriendShip(@RequestBody @Validated ImporFriendShipReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.importFriendShip(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/addFriend")
|
||||
public ResponseVO addFriend(@RequestBody @Validated AddFriendReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.addFriend(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/updateFriend")
|
||||
public ResponseVO updateFriend(@RequestBody @Validated UpdateFriendReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.updateFriend(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/deleteFriend")
|
||||
public ResponseVO deleteFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.deleteFriend(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/deleteAllFriend")
|
||||
public ResponseVO deleteAllFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.deleteAllFriend(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/getAllFriendShip")
|
||||
public ResponseVO getAllFriendShip(@RequestBody @Validated GetAllFriendShipReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.getAllFriendShip(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/getRelation")
|
||||
public ResponseVO getRelation(@RequestBody @Validated GetRelationReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.getRelation(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/checkFriend")
|
||||
public ResponseVO checkFriend(@RequestBody @Validated CheckFriendShipReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.checkFriendship(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/addBlack")
|
||||
public ResponseVO addBlack(@RequestBody @Validated AddFriendShipBlackReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.addBlack(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/deleteBlack")
|
||||
public ResponseVO deleteBlack(@RequestBody @Validated DeleteBlackReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.deleteBlack(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/checkBlck")
|
||||
public ResponseVO checkBlck(@RequestBody @Validated CheckFriendShipReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.checkBlck(req);
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/syncFriendshipList")
|
||||
public ResponseVO syncFriendshipList(@RequestBody @Validated
|
||||
SyncReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipService.syncFriendshipList(req);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.lld.im.service.friendship.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("v1/friendship/group")
|
||||
public class ImFriendShipGroupController {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupService imFriendShipGroupService;
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupMemberService imFriendShipGroupMemberService;
|
||||
|
||||
|
||||
@RequestMapping("/add")
|
||||
public ResponseVO add(@RequestBody @Validated AddFriendShipGroupReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return imFriendShipGroupService.addGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/del")
|
||||
public ResponseVO del(@RequestBody @Validated DeleteFriendShipGroupReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return imFriendShipGroupService.deleteGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/member/add")
|
||||
public ResponseVO memberAdd(@RequestBody @Validated AddFriendShipGroupMemberReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return imFriendShipGroupMemberService.addGroupMember(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/member/del")
|
||||
public ResponseVO memberdel(@RequestBody @Validated DeleteFriendShipGroupMemberReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return imFriendShipGroupMemberService.delGroupMember(req);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.lld.im.service.friendship.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq;
|
||||
import com.lld.im.service.friendship.model.req.GetFriendShipRequestReq;
|
||||
import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipRequestService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("v1/friendshipRequest")
|
||||
public class ImFriendShipRequestController {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipRequestService imFriendShipRequestService;
|
||||
|
||||
@RequestMapping("/approveFriendRequest")
|
||||
public ResponseVO approveFriendRequest(@RequestBody @Validated
|
||||
ApproverFriendRequestReq req, Integer appId, String identifier){
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return imFriendShipRequestService.approverFriendRequest(req);
|
||||
}
|
||||
@RequestMapping("/getFriendRequest")
|
||||
public ResponseVO getFriendRequest(@RequestBody @Validated GetFriendShipRequestReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipRequestService.getFriendRequest(req.getFromId(),req.getAppId());
|
||||
}
|
||||
|
||||
@RequestMapping("/readFriendShipRequestReq")
|
||||
public ResponseVO readFriendShipRequestReq(@RequestBody @Validated ReadFriendShipRequestReq req, Integer appId){
|
||||
req.setAppId(appId);
|
||||
return imFriendShipRequestService.readFriendShipRequestReq(req);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.lld.im.service.friendship.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.github.jeffreyning.mybatisplus.anno.AutoMap;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
|
||||
@Data
|
||||
@TableName("im_friendship")
|
||||
@AutoMap
|
||||
public class ImFriendShipEntity {
|
||||
|
||||
@TableField(value = "app_id")
|
||||
private Integer appId;
|
||||
|
||||
@TableField(value = "from_id")
|
||||
private String fromId;
|
||||
|
||||
@TableField(value = "to_id")
|
||||
private String toId;
|
||||
/** 备注*/
|
||||
private String remark;
|
||||
/** 状态 1正常 2删除*/
|
||||
private Integer status;
|
||||
/** 状态 1正常 2拉黑*/
|
||||
private Integer black;
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private Long createTime;
|
||||
/** 好友关系序列号*/
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private Long friendSequence;
|
||||
|
||||
/** 黑名单关系序列号*/
|
||||
private Long blackSequence;
|
||||
/** 好友来源*/
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private String addSource;
|
||||
|
||||
private String extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.lld.im.service.friendship.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("im_friendship_group")
|
||||
public class ImFriendShipGroupEntity {
|
||||
|
||||
@TableId(value = "group_id",type = IdType.AUTO)
|
||||
private Long groupId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
private String groupName;
|
||||
/** 备注*/
|
||||
private Long createTime;
|
||||
|
||||
/** 备注*/
|
||||
private Long updateTime;
|
||||
|
||||
/** 序列号*/
|
||||
private Long sequence;
|
||||
|
||||
private int delFlag;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lld.im.service.friendship.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
@TableName("im_friendship_group_member")
|
||||
public class ImFriendShipGroupMemberEntity {
|
||||
|
||||
@TableId(value = "group_id")
|
||||
private Long groupId;
|
||||
|
||||
private String toId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.lld.im.service.friendship.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
@TableName("im_friendship_request")
|
||||
public class ImFriendShipRequestEntity {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
/** 备注*/
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private String remark;
|
||||
|
||||
//是否已读 1已读
|
||||
private Integer readStatus;
|
||||
|
||||
/** 好友来源*/
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private String addSource;
|
||||
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private String addWording;
|
||||
|
||||
//审批状态 1同意 2拒绝
|
||||
private Integer approveStatus;
|
||||
|
||||
// @TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||
private Long createTime;
|
||||
|
||||
private Long updateTime;
|
||||
|
||||
/** 序列号*/
|
||||
private Long sequence;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lld.im.service.friendship.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity;
|
||||
|
||||
public interface ImFriendShipGroupMapper extends BaseMapper<ImFriendShipGroupEntity> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lld.im.service.friendship.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity;
|
||||
|
||||
public interface ImFriendShipGroupMemberMapper extends BaseMapper<ImFriendShipGroupMemberEntity> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.lld.im.service.friendship.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipEntity;
|
||||
import com.lld.im.service.friendship.model.req.CheckFriendShipReq;
|
||||
import com.lld.im.service.friendship.model.resp.CheckFriendShipResp;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ImFriendShipMapper extends BaseMapper<ImFriendShipEntity> {
|
||||
|
||||
|
||||
|
||||
|
||||
@Select("<script>"+
|
||||
"select from_id as fromId , to_id as toId ,if(status = 1,1,0) as status from im_friendship where from_id = #{fromId} and to_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close = ')' open='(' > " +
|
||||
"#{id}" +
|
||||
"</foreach>" +
|
||||
" and app_id = #{appId} " +
|
||||
"</script>")
|
||||
public List<CheckFriendShipResp> checkFriendShip(CheckFriendShipReq req);
|
||||
|
||||
|
||||
@Select("<script>" +
|
||||
" select a.fromId,a.toId , ( \n" +
|
||||
" case \n" +
|
||||
" when a.status = 1 and b.status = 1 then 1 \n" +
|
||||
" when a.status = 1 and b.status != 1 then 2 \n" +
|
||||
" when a.status != 1 and b.status = 1 then 3 \n" +
|
||||
" when a.status != 1 and b.status != 1 then 4 \n" +
|
||||
" end \n" +
|
||||
" ) \n " +
|
||||
" as status from "+
|
||||
" (select from_id AS fromId , to_id AS toId , if(status = 1,1,0) as status from im_friendship where app_id = #{appId} and from_id = #{fromId} AND to_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
" ) as a INNER join" +
|
||||
" (select from_id AS fromId, to_id AS toId , if(status = 1,1,0) as status from im_friendship where app_id = #{appId} and to_id = #{fromId} AND from_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
" ) as b " +
|
||||
" on a.fromId = b.toId AND b.fromId = a.toId "+
|
||||
"</script>"
|
||||
)
|
||||
List<CheckFriendShipResp> checkFriendShipBoth(CheckFriendShipReq toId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Select("<script>" +
|
||||
" select from_id AS fromId, to_id AS toId , if(black = 1,1,0) as status from im_friendship where app_id = #{appId} and from_id = #{fromId} and to_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
"</script>"
|
||||
)
|
||||
List<CheckFriendShipResp> checkFriendShipBlack(CheckFriendShipReq req);
|
||||
|
||||
@Select("<script>" +
|
||||
" select a.fromId,a.toId , ( \n" +
|
||||
" case \n" +
|
||||
" when a.black = 1 and b.black = 1 then 1 \n" +
|
||||
" when a.black = 1 and b.black != 1 then 2 \n" +
|
||||
" when a.black != 1 and b.black = 1 then 3 \n" +
|
||||
" when a.black != 1 and b.black != 1 then 4 \n" +
|
||||
" end \n" +
|
||||
" ) \n " +
|
||||
" as status from "+
|
||||
" (select from_id AS fromId , to_id AS toId , if(black = 1,1,0) as black from im_friendship where app_id = #{appId} and from_id = #{fromId} AND to_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
" ) as a INNER join" +
|
||||
" (select from_id AS fromId, to_id AS toId , if(black = 1,1,0) as black from im_friendship where app_id = #{appId} and to_id = #{fromId} AND from_id in " +
|
||||
"<foreach collection='toIds' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
" ) as b " +
|
||||
" on a.fromId = b.toId AND b.fromId = a.toId "+
|
||||
"</script>"
|
||||
)
|
||||
List<CheckFriendShipResp> checkFriendShipBlackBoth(CheckFriendShipReq toId);
|
||||
|
||||
@Select(" select max(friend_sequence) from im_friendship where app_id = #{appId} AND from_id = #{userId} ")
|
||||
Long getFriendShipMaxSeq(Integer appId,String userId);
|
||||
|
||||
@Select(
|
||||
" select to_id from im_friendship where from_id = #{userId} AND app_id = #{appId} and status = 1 and black = 1 "
|
||||
)
|
||||
List<String> getAllFriendId(String userId,Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lld.im.service.friendship.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ImFriendShipRequestMapper extends BaseMapper<ImFriendShipRequestEntity> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lld.im.service.friendship.model.callback;
|
||||
|
||||
import com.lld.im.service.friendship.model.req.FriendDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class AddFriendAfterCallbackDto {
|
||||
|
||||
private String fromId;
|
||||
|
||||
private FriendDto toItem;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lld.im.service.friendship.model.callback;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class AddFriendBlackAfterCallbackDto {
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lld.im.service.friendship.model.callback;
|
||||
|
||||
import com.lld.im.service.friendship.model.req.FriendDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class DeleteFriendAfterCallbackDto {
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
@Data
|
||||
public class AddFriendReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotNull(message = "toItem不能为空")
|
||||
private FriendDto toItem;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class AddFriendShipBlackReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class AddFriendShipGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotBlank(message = "分组名称不能为空")
|
||||
private String groupName;
|
||||
|
||||
@NotEmpty(message = "请选择用户")
|
||||
private List<String> toIds;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class AddFriendShipGroupReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
public String fromId;
|
||||
|
||||
@NotBlank(message = "分组名称不能为空")
|
||||
private String groupName;
|
||||
|
||||
private List<String> toIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class ApproverFriendRequestReq extends RequestBase {
|
||||
|
||||
private Long id;
|
||||
|
||||
//1同意 2拒绝
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class CheckFriendShipReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotEmpty(message = "toIds不能为空")
|
||||
private List<String> toIds;
|
||||
|
||||
@NotNull(message = "checkType不能为空")
|
||||
private Integer checkType;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class DeleteBlackReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotBlank(message = "好友id不能为空")
|
||||
private String toId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class DeleteFriendReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotBlank(message = "toId不能为空")
|
||||
private String toId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class DeleteFriendShipGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotBlank(message = "分组名称不能为空")
|
||||
private String groupName;
|
||||
|
||||
@NotEmpty(message = "请选择用户")
|
||||
private List<String> toIds;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description: 删除分组,同时删除分组下的成员
|
||||
**/
|
||||
@Data
|
||||
public class DeleteFriendShipGroupReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotEmpty(message = "分组名称不能为空")
|
||||
private List<String> groupName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class FriendDto {
|
||||
|
||||
private String toId;
|
||||
|
||||
private String remark;
|
||||
|
||||
private String addSource;
|
||||
|
||||
private String extra;
|
||||
|
||||
private String addWording;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class GetAllFriendShipReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String fromId;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class GetFriendShipRequestReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String fromId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class GetRelationReq extends RequestBase {
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotBlank(message = "toId不能为空")
|
||||
private String toId;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.enums.FriendShipStatusEnum;
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class ImporFriendShipReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
private List<ImportFriendDto> friendItem;
|
||||
|
||||
@Data
|
||||
public static class ImportFriendDto{
|
||||
|
||||
private String toId;
|
||||
|
||||
private String remark;
|
||||
|
||||
private String addSource;
|
||||
|
||||
private Integer status = FriendShipStatusEnum.FRIEND_STATUS_NO_FRIEND.getCode();
|
||||
|
||||
private Integer black = FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
|
||||
@Data
|
||||
public class ReadFriendShipRequestReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String fromId;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.friendship.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
@Data
|
||||
public class UpdateFriendReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "fromId不能为空")
|
||||
private String fromId;
|
||||
|
||||
@NotNull(message = "toItem不能为空")
|
||||
private FriendDto toItem;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lld.im.service.friendship.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class CheckFriendShipResp {
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
|
||||
|
||||
//校验状态,根据双向校验和单向校验有不同的status
|
||||
//单向校验:1 from添加了to,不确定to是否添加了from CheckResult_single_Type_AWithB;
|
||||
// 0 from没有添加to,也不确定to有没有添加from CheckResult_single_Type_NoRelation
|
||||
//双向校验 1 from添加了to,to也添加了from CheckResult_Type_BothWay
|
||||
// 2 from添加了t0,to没有添加from CheckResult_Both_Type_AWithB
|
||||
// 3 from没有添加to,to添加了from, CheckResult_Both_Type_BWithA
|
||||
// 4 双方都没有添加 CheckResult_Both_Type_NoRelation
|
||||
|
||||
//单向校验黑名单:1 from没有拉黑to,不确定to是否拉黑了from CheckResult_singe_Type_AWithB;
|
||||
// 0 from拉黑to,不确定to是佛拉黑from CheckResult_singe_Type_NoRelation
|
||||
//双向校验黑名单 1 from没有拉黑to,to也没有拉黑from CheckResult_Type_BothWay
|
||||
// 2 from没有拉黑to,to拉黑from CheckResult_Both_Type_AWithB
|
||||
// 3 from拉黑了to,to没有拉黑from CheckResult_Both_Type_BWithA
|
||||
// 4 双方都拉黑 CheckResult_Both_Type_NoRelation
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lld.im.service.friendship.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class ImportFriendShipResp {
|
||||
|
||||
private List<String> successId;
|
||||
|
||||
private List<String> errorId;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lld.im.service.friendship.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.service.friendship.model.req.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface ImFriendService {
|
||||
|
||||
public ResponseVO importFriendShip(ImporFriendShipReq req);
|
||||
|
||||
public ResponseVO addFriend(AddFriendReq req);
|
||||
|
||||
public ResponseVO updateFriend(UpdateFriendReq req);
|
||||
|
||||
public ResponseVO deleteFriend(DeleteFriendReq req);
|
||||
|
||||
public ResponseVO deleteAllFriend(DeleteFriendReq req);
|
||||
|
||||
public ResponseVO getAllFriendShip(GetAllFriendShipReq req);
|
||||
|
||||
public ResponseVO getRelation(GetRelationReq req);
|
||||
|
||||
public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId);
|
||||
|
||||
public ResponseVO checkFriendship(CheckFriendShipReq req);
|
||||
|
||||
public ResponseVO addBlack(AddFriendShipBlackReq req);
|
||||
|
||||
public ResponseVO deleteBlack(DeleteBlackReq req);
|
||||
|
||||
public ResponseVO checkBlck(CheckFriendShipReq req);
|
||||
|
||||
public ResponseVO syncFriendshipList(SyncReq req);
|
||||
|
||||
public List<String> getAllFriendId(String userId, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.lld.im.service.friendship.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
public interface ImFriendShipGroupMemberService {
|
||||
|
||||
public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req);
|
||||
|
||||
public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req);
|
||||
|
||||
public int doAddGroupMember(Long groupId, String toId);
|
||||
|
||||
public int clearGroupMember(Long groupId);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lld.im.service.friendship.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
public interface ImFriendShipGroupService {
|
||||
|
||||
public ResponseVO addGroup(AddFriendShipGroupReq req);
|
||||
|
||||
public ResponseVO deleteGroup(DeleteFriendShipGroupReq req);
|
||||
|
||||
public ResponseVO<ImFriendShipGroupEntity> getGroup(String fromId, String groupName, Integer appId);
|
||||
|
||||
public Long updateSeq(String fromId, String groupName, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.friendship.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq;
|
||||
import com.lld.im.service.friendship.model.req.FriendDto;
|
||||
import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq;
|
||||
|
||||
|
||||
public interface ImFriendShipRequestService {
|
||||
|
||||
public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId);
|
||||
|
||||
public ResponseVO approverFriendRequest(ApproverFriendRequestReq req);
|
||||
|
||||
public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req);
|
||||
|
||||
public ResponseVO getFriendRequest(String fromId, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,664 @@
|
||||
package com.lld.im.service.friendship.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.lld.im.codec.pack.friendship.*;
|
||||
import com.lld.im.codec.proto.Message;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.AllowFriendTypeEnum;
|
||||
import com.lld.im.common.enums.CheckFriendShipTypeEnum;
|
||||
import com.lld.im.common.enums.FriendShipErrorCode;
|
||||
import com.lld.im.common.enums.FriendShipStatusEnum;
|
||||
import com.lld.im.common.enums.command.FriendshipEventCommand;
|
||||
import com.lld.im.common.exception.ApplicationException;
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.common.model.SyncResp;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipEntity;
|
||||
import com.lld.im.service.friendship.dao.mapper.ImFriendShipMapper;
|
||||
import com.lld.im.service.friendship.model.callback.AddFriendAfterCallbackDto;
|
||||
import com.lld.im.service.friendship.model.callback.AddFriendBlackAfterCallbackDto;
|
||||
import com.lld.im.service.friendship.model.callback.DeleteFriendAfterCallbackDto;
|
||||
import com.lld.im.service.friendship.model.req.*;
|
||||
import com.lld.im.service.friendship.model.resp.CheckFriendShipResp;
|
||||
import com.lld.im.service.friendship.model.resp.ImportFriendShipResp;
|
||||
import com.lld.im.service.friendship.service.ImFriendService;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipRequestService;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.user.dao.ImUserDataEntity;
|
||||
import com.lld.im.service.user.service.ImUserService;
|
||||
import com.lld.im.service.utils.CallbackService;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import com.lld.im.service.utils.WriteUserSeq;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class ImFriendServiceImpl implements ImFriendService {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipMapper imFriendShipMapper;
|
||||
|
||||
@Autowired
|
||||
ImUserService imUserService;
|
||||
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Autowired
|
||||
CallbackService callbackService;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Autowired
|
||||
ImFriendService imFriendService;
|
||||
|
||||
@Autowired
|
||||
ImFriendShipRequestService imFriendShipRequestService;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
@Autowired
|
||||
WriteUserSeq writeUserSeq;
|
||||
|
||||
@Override
|
||||
public ResponseVO importFriendShip(ImporFriendShipReq req) {
|
||||
|
||||
if(req.getFriendItem().size() > 100){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.IMPORT_SIZE_BEYOND);
|
||||
}
|
||||
ImportFriendShipResp resp = new ImportFriendShipResp();
|
||||
List<String> successId = new ArrayList<>();
|
||||
List<String> errorId = new ArrayList<>();
|
||||
|
||||
for (ImporFriendShipReq.ImportFriendDto dto:
|
||||
req.getFriendItem()) {
|
||||
ImFriendShipEntity entity = new ImFriendShipEntity();
|
||||
BeanUtils.copyProperties(dto,entity);
|
||||
entity.setAppId(req.getAppId());
|
||||
entity.setFromId(req.getFromId());
|
||||
try {
|
||||
int insert = imFriendShipMapper.insert(entity);
|
||||
if(insert == 1){
|
||||
successId.add(dto.getToId());
|
||||
}else{
|
||||
errorId.add(dto.getToId());
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
errorId.add(dto.getToId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resp.setErrorId(errorId);
|
||||
resp.setSuccessId(successId);
|
||||
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO addFriend(AddFriendReq req) {
|
||||
|
||||
ResponseVO<ImUserDataEntity> fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId());
|
||||
if(!fromInfo.isOk()){
|
||||
return fromInfo;
|
||||
}
|
||||
|
||||
ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId());
|
||||
if(!toInfo.isOk()){
|
||||
return toInfo;
|
||||
}
|
||||
|
||||
if(appConfig.isAddFriendBeforeCallback()){
|
||||
ResponseVO callbackResp = callbackService
|
||||
.beforeCallback(req.getAppId(),
|
||||
Constants.CallbackCommand.AddFriendBefore
|
||||
,JSONObject.toJSONString(req));
|
||||
if(!callbackResp.isOk()){
|
||||
return callbackResp;
|
||||
}
|
||||
}
|
||||
|
||||
ImUserDataEntity data = toInfo.getData();
|
||||
|
||||
if(data.getFriendAllowType() != null && data.getFriendAllowType() == AllowFriendTypeEnum.NOT_NEED.getCode()){
|
||||
return this.doAddFriend(req,req.getFromId(), req.getToItem(), req.getAppId());
|
||||
}else{
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
query.eq("to_id",req.getToItem().getToId());
|
||||
ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
|
||||
if(fromItem == null || fromItem.getStatus()
|
||||
!= FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){
|
||||
//插入一条好友申请的数据
|
||||
ResponseVO responseVO = imFriendShipRequestService.addFienshipRequest(req.getFromId(), req.getToItem(), req.getAppId());
|
||||
if(!responseVO.isOk()){
|
||||
return responseVO;
|
||||
}
|
||||
}else{
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO updateFriend(UpdateFriendReq req) {
|
||||
|
||||
ResponseVO<ImUserDataEntity> fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId());
|
||||
if(!fromInfo.isOk()){
|
||||
return fromInfo;
|
||||
}
|
||||
|
||||
ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId());
|
||||
if(!toInfo.isOk()){
|
||||
return toInfo;
|
||||
}
|
||||
|
||||
ResponseVO responseVO = this.doUpdate(req.getFromId(), req.getToItem(), req.getAppId());
|
||||
if(responseVO.isOk()){
|
||||
UpdateFriendPack updateFriendPack = new UpdateFriendPack();
|
||||
updateFriendPack.setRemark(req.getToItem().getRemark());
|
||||
updateFriendPack.setToId(req.getToItem().getToId());
|
||||
messageProducer.sendToUser(req.getFromId(),
|
||||
req.getClientType(),req.getImei(),FriendshipEventCommand
|
||||
.FRIEND_UPDATE,updateFriendPack,req.getAppId());
|
||||
|
||||
if (appConfig.isModifyFriendAfterCallback()) {
|
||||
AddFriendAfterCallbackDto callbackDto = new AddFriendAfterCallbackDto();
|
||||
callbackDto.setFromId(req.getFromId());
|
||||
callbackDto.setToItem(req.getToItem());
|
||||
callbackService.beforeCallback(req.getAppId(),
|
||||
Constants.CallbackCommand.UpdateFriendAfter, JSONObject
|
||||
.toJSONString(callbackDto));
|
||||
}
|
||||
}
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ResponseVO doUpdate(String fromId, FriendDto dto,Integer appId){
|
||||
|
||||
|
||||
long seq = redisSeq.doGetSeq(appId + ":" + Constants.SeqConstants.Friendship);
|
||||
UpdateWrapper<ImFriendShipEntity> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.lambda().set(ImFriendShipEntity::getAddSource,dto.getAddSource())
|
||||
.set(ImFriendShipEntity::getExtra,dto.getExtra())
|
||||
.set(ImFriendShipEntity::getFriendSequence,seq)
|
||||
.set(ImFriendShipEntity::getRemark,dto.getRemark())
|
||||
.eq(ImFriendShipEntity::getAppId,appId)
|
||||
.eq(ImFriendShipEntity::getToId,dto.getToId())
|
||||
.eq(ImFriendShipEntity::getFromId,fromId);
|
||||
|
||||
int update = imFriendShipMapper.update(null, updateWrapper);
|
||||
if(update == 1){
|
||||
//之后回调
|
||||
// if (appConfig.isModifyFriendAfterCallback()){
|
||||
// AddFriendAfterCallbackDto callbackDto = new AddFriendAfterCallbackDto();
|
||||
// callbackDto.setFromId(fromId);
|
||||
// callbackDto.setToItem(dto);
|
||||
// callbackService.beforeCallback(appId,
|
||||
// Constants.CallbackCommand.UpdateFriendAfter, JSONObject
|
||||
// .toJSONString(callbackDto));
|
||||
// }
|
||||
writeUserSeq.writeUserSeq(appId,fromId,Constants.SeqConstants.Friendship,seq);
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
return ResponseVO.errorResponse();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId){
|
||||
|
||||
//A-B
|
||||
//Friend表插入A 和 B 两条记录
|
||||
//查询是否有记录存在,如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态
|
||||
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",appId);
|
||||
query.eq("from_id",fromId);
|
||||
query.eq("to_id",dto.getToId());
|
||||
ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
|
||||
long seq = 0L;
|
||||
if(fromItem == null){
|
||||
//走添加逻辑。
|
||||
fromItem = new ImFriendShipEntity();
|
||||
seq = redisSeq.doGetSeq(appId+":"+Constants.SeqConstants.Friendship);
|
||||
fromItem.setAppId(appId);
|
||||
fromItem.setFriendSequence(seq);
|
||||
fromItem.setFromId(fromId);
|
||||
// entity.setToId(to);
|
||||
BeanUtils.copyProperties(dto,fromItem);
|
||||
fromItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
|
||||
fromItem.setCreateTime(System.currentTimeMillis());
|
||||
int insert = imFriendShipMapper.insert(fromItem);
|
||||
if(insert != 1){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR);
|
||||
}
|
||||
writeUserSeq.writeUserSeq(appId,fromId,Constants.SeqConstants.Friendship,seq);
|
||||
} else{
|
||||
//如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态
|
||||
|
||||
if(fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND);
|
||||
} else{
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
|
||||
if(StringUtils.isNotBlank(dto.getAddSource())){
|
||||
update.setAddSource(dto.getAddSource());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotBlank(dto.getRemark())){
|
||||
update.setRemark(dto.getRemark());
|
||||
}
|
||||
|
||||
if(StringUtils.isNotBlank(dto.getExtra())){
|
||||
update.setExtra(dto.getExtra());
|
||||
}
|
||||
seq = redisSeq.doGetSeq(appId+":"+Constants.SeqConstants.Friendship);
|
||||
update.setFriendSequence(seq);
|
||||
update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
|
||||
|
||||
int result = imFriendShipMapper.update(update, query);
|
||||
if(result != 1){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR);
|
||||
}
|
||||
writeUserSeq.writeUserSeq(appId,fromId,Constants.SeqConstants.Friendship,seq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QueryWrapper<ImFriendShipEntity> toQuery = new QueryWrapper<>();
|
||||
toQuery.eq("app_id",appId);
|
||||
toQuery.eq("from_id",dto.getToId());
|
||||
toQuery.eq("to_id",fromId);
|
||||
ImFriendShipEntity toItem = imFriendShipMapper.selectOne(toQuery);
|
||||
if(toItem == null){
|
||||
toItem = new ImFriendShipEntity();
|
||||
toItem.setAppId(appId);
|
||||
toItem.setFromId(dto.getToId());
|
||||
BeanUtils.copyProperties(dto,toItem);
|
||||
toItem.setToId(fromId);
|
||||
toItem.setFriendSequence(seq);
|
||||
toItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
|
||||
toItem.setCreateTime(System.currentTimeMillis());
|
||||
// toItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode());
|
||||
int insert = imFriendShipMapper.insert(toItem);
|
||||
writeUserSeq.writeUserSeq(appId,dto.getToId(),Constants.SeqConstants.Friendship,seq);
|
||||
}else{
|
||||
if(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode() !=
|
||||
toItem.getStatus()){
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
update.setFriendSequence(seq);
|
||||
update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
|
||||
imFriendShipMapper.update(update,toQuery);
|
||||
writeUserSeq.writeUserSeq(appId,dto.getToId(),Constants.SeqConstants.Friendship,seq);
|
||||
}
|
||||
}
|
||||
|
||||
//发送给from
|
||||
AddFriendPack addFriendPack = new AddFriendPack();
|
||||
BeanUtils.copyProperties(fromItem,addFriendPack);
|
||||
addFriendPack.setSequence(seq);
|
||||
if(requestBase != null){
|
||||
messageProducer.sendToUser(fromId,requestBase.getClientType(),
|
||||
requestBase.getImei(), FriendshipEventCommand.FRIEND_ADD,addFriendPack
|
||||
,requestBase.getAppId());
|
||||
}else {
|
||||
messageProducer.sendToUser(fromId,
|
||||
FriendshipEventCommand.FRIEND_ADD,addFriendPack
|
||||
,requestBase.getAppId());
|
||||
}
|
||||
|
||||
AddFriendPack addFriendToPack = new AddFriendPack();
|
||||
BeanUtils.copyProperties(toItem,addFriendPack);
|
||||
messageProducer.sendToUser(toItem.getFromId(),
|
||||
FriendshipEventCommand.FRIEND_ADD,addFriendToPack
|
||||
,requestBase.getAppId());
|
||||
|
||||
//之后回调
|
||||
if (appConfig.isAddFriendAfterCallback()){
|
||||
AddFriendAfterCallbackDto callbackDto = new AddFriendAfterCallbackDto();
|
||||
callbackDto.setFromId(fromId);
|
||||
callbackDto.setToItem(dto);
|
||||
callbackService.beforeCallback(appId,
|
||||
Constants.CallbackCommand.AddFriendAfter, JSONObject
|
||||
.toJSONString(callbackDto));
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResponseVO deleteFriend(DeleteFriendReq req) {
|
||||
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
query.eq("to_id",req.getToId());
|
||||
ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
|
||||
if(fromItem == null){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_NOT_YOUR_FRIEND);
|
||||
}else{
|
||||
if(fromItem.getStatus() != null && fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Friendship);
|
||||
update.setFriendSequence(seq);
|
||||
update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode());
|
||||
imFriendShipMapper.update(update,query);
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getFromId(),Constants.SeqConstants.Friendship,seq);
|
||||
DeleteFriendPack deleteFriendPack = new DeleteFriendPack();
|
||||
deleteFriendPack.setFromId(req.getFromId());
|
||||
deleteFriendPack.setSequence(seq);
|
||||
deleteFriendPack.setToId(req.getToId());
|
||||
messageProducer.sendToUser(req.getFromId(),
|
||||
req.getClientType(), req.getImei(),
|
||||
FriendshipEventCommand.FRIEND_DELETE,
|
||||
deleteFriendPack, req.getAppId());
|
||||
|
||||
//之后回调
|
||||
if (appConfig.isAddFriendAfterCallback()){
|
||||
DeleteFriendAfterCallbackDto callbackDto = new DeleteFriendAfterCallbackDto();
|
||||
callbackDto.setFromId(req.getFromId());
|
||||
callbackDto.setToId(req.getToId());
|
||||
callbackService.beforeCallback(req.getAppId(),
|
||||
Constants.CallbackCommand.DeleteFriendAfter, JSONObject
|
||||
.toJSONString(callbackDto));
|
||||
}
|
||||
|
||||
}else{
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_DELETED);
|
||||
}
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO deleteAllFriend(DeleteFriendReq req) {
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
query.eq("status",FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode());
|
||||
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode());
|
||||
imFriendShipMapper.update(update,query);
|
||||
|
||||
DeleteAllFriendPack deleteFriendPack = new DeleteAllFriendPack();
|
||||
deleteFriendPack.setFromId(req.getFromId());
|
||||
messageProducer.sendToUser(req.getFromId(), req.getClientType(), req.getImei(), FriendshipEventCommand.FRIEND_ALL_DELETE,
|
||||
deleteFriendPack, req.getAppId());
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO getAllFriendShip(GetAllFriendShipReq req) {
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
return ResponseVO.successResponse(imFriendShipMapper.selectList(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO getRelation(GetRelationReq req) {
|
||||
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
query.eq("to_id",req.getToId());
|
||||
|
||||
ImFriendShipEntity entity = imFriendShipMapper.selectOne(query);
|
||||
if(entity == null){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.REPEATSHIP_IS_NOT_EXIST);
|
||||
}
|
||||
return ResponseVO.successResponse(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO checkBlck(CheckFriendShipReq req) {
|
||||
|
||||
Map<String, Integer> toIdMap
|
||||
= req.getToIds().stream().collect(Collectors
|
||||
.toMap(Function.identity(), s -> 0));
|
||||
List<CheckFriendShipResp> result = new ArrayList<>();
|
||||
if (req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()) {
|
||||
result = imFriendShipMapper.checkFriendShipBlack(req);
|
||||
} else {
|
||||
result = imFriendShipMapper.checkFriendShipBlackBoth(req);
|
||||
}
|
||||
|
||||
Map<String, Integer> collect = result.stream()
|
||||
.collect(Collectors
|
||||
.toMap(CheckFriendShipResp::getToId,
|
||||
CheckFriendShipResp::getStatus));
|
||||
for (String toId:
|
||||
toIdMap.keySet()) {
|
||||
if(!collect.containsKey(toId)){
|
||||
CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp();
|
||||
checkFriendShipResp.setToId(toId);
|
||||
checkFriendShipResp.setFromId(req.getFromId());
|
||||
checkFriendShipResp.setStatus(toIdMap.get(toId));
|
||||
result.add(checkFriendShipResp);
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO syncFriendshipList(SyncReq req) {
|
||||
|
||||
if(req.getMaxLimit() > 100){
|
||||
req.setMaxLimit(100);
|
||||
}
|
||||
|
||||
SyncResp<ImFriendShipEntity> resp = new SyncResp<>();
|
||||
//seq > req.getseq limit maxLimit
|
||||
QueryWrapper<ImFriendShipEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("from_id",req.getOperater());
|
||||
queryWrapper.gt("friend_sequence",req.getLastSequence());
|
||||
queryWrapper.eq("app_id",req.getAppId());
|
||||
queryWrapper.last(" limit " + req.getMaxLimit());
|
||||
queryWrapper.orderByAsc("friend_sequence");
|
||||
List<ImFriendShipEntity> list = imFriendShipMapper.selectList(queryWrapper);
|
||||
|
||||
if(!CollectionUtils.isEmpty(list)){
|
||||
ImFriendShipEntity maxSeqEntity = list.get(list.size() - 1);
|
||||
resp.setDataList(list);
|
||||
//设置最大seq
|
||||
Long friendShipMaxSeq = imFriendShipMapper.getFriendShipMaxSeq(req.getAppId(), req.getOperater());
|
||||
resp.setMaxSequence(friendShipMaxSeq);
|
||||
//设置是否拉取完毕
|
||||
resp.setCompleted(maxSeqEntity.getFriendSequence() >= friendShipMaxSeq);
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
resp.setCompleted(true);
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllFriendId(String userId, Integer appId) {
|
||||
return imFriendShipMapper.getAllFriendId(userId,appId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO addBlack(AddFriendShipBlackReq req) {
|
||||
|
||||
ResponseVO<ImUserDataEntity> fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId());
|
||||
if(!fromInfo.isOk()){
|
||||
return fromInfo;
|
||||
}
|
||||
|
||||
ResponseVO<ImUserDataEntity> toInfo = imUserService.getSingleUserInfo(req.getToId(), req.getAppId());
|
||||
if(!toInfo.isOk()){
|
||||
return toInfo;
|
||||
}
|
||||
QueryWrapper<ImFriendShipEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id",req.getAppId());
|
||||
query.eq("from_id",req.getFromId());
|
||||
query.eq("to_id",req.getToId());
|
||||
|
||||
ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query);
|
||||
Long seq = 0L;
|
||||
if(fromItem == null){
|
||||
//走添加逻辑。
|
||||
seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Friendship);
|
||||
|
||||
fromItem = new ImFriendShipEntity();
|
||||
fromItem.setFromId(req.getFromId());
|
||||
fromItem.setToId(req.getToId());
|
||||
fromItem.setFriendSequence(seq);
|
||||
fromItem.setAppId(req.getAppId());
|
||||
fromItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode());
|
||||
fromItem.setCreateTime(System.currentTimeMillis());
|
||||
int insert = imFriendShipMapper.insert(fromItem);
|
||||
if(insert != 1){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR);
|
||||
}
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getFromId(),Constants.SeqConstants.Friendship,seq);
|
||||
|
||||
} else{
|
||||
//如果存在则判断状态,如果是拉黑,则提示已拉黑,如果是未拉黑,则修改状态
|
||||
if(fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_BLACK);
|
||||
}
|
||||
|
||||
else {
|
||||
seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Friendship);
|
||||
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
update.setFriendSequence(seq);
|
||||
update.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode());
|
||||
int result = imFriendShipMapper.update(update, query);
|
||||
if(result != 1){
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.ADD_BLACK_ERROR);
|
||||
}
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getFromId(),Constants.SeqConstants.Friendship,seq);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AddFriendBlackPack addFriendBlackPack = new AddFriendBlackPack();
|
||||
addFriendBlackPack.setFromId(req.getFromId());
|
||||
addFriendBlackPack.setSequence(seq);
|
||||
addFriendBlackPack.setToId(req.getToId());
|
||||
//发送tcp通知
|
||||
messageProducer.sendToUser(req.getFromId(), req.getClientType(), req.getImei(),
|
||||
FriendshipEventCommand.FRIEND_BLACK_ADD, addFriendBlackPack, req.getAppId());
|
||||
|
||||
//之后回调
|
||||
if (appConfig.isAddFriendShipBlackAfterCallback()){
|
||||
AddFriendBlackAfterCallbackDto callbackDto = new AddFriendBlackAfterCallbackDto();
|
||||
callbackDto.setFromId(req.getFromId());
|
||||
callbackDto.setToId(req.getToId());
|
||||
callbackService.beforeCallback(req.getAppId(),
|
||||
Constants.CallbackCommand.AddBlackAfter, JSONObject
|
||||
.toJSONString(callbackDto));
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO deleteBlack(DeleteBlackReq req) {
|
||||
QueryWrapper queryFrom = new QueryWrapper<>()
|
||||
.eq("from_id", req.getFromId())
|
||||
.eq("app_id", req.getAppId())
|
||||
.eq("to_id", req.getToId());
|
||||
ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(queryFrom);
|
||||
if (fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()) {
|
||||
throw new ApplicationException(FriendShipErrorCode.FRIEND_IS_NOT_YOUR_BLACK);
|
||||
}
|
||||
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Friendship);
|
||||
|
||||
ImFriendShipEntity update = new ImFriendShipEntity();
|
||||
update.setFriendSequence(seq);
|
||||
update.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode());
|
||||
int update1 = imFriendShipMapper.update(update, queryFrom);
|
||||
if(update1 == 1){
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getFromId(),Constants.SeqConstants.Friendship,seq);
|
||||
DeleteBlackPack deleteFriendPack = new DeleteBlackPack();
|
||||
deleteFriendPack.setFromId(req.getFromId());
|
||||
deleteFriendPack.setSequence(seq);
|
||||
deleteFriendPack.setToId(req.getToId());
|
||||
messageProducer.sendToUser(req.getFromId(), req.getClientType(), req.getImei(), FriendshipEventCommand.FRIEND_BLACK_DELETE,
|
||||
deleteFriendPack, req.getAppId());
|
||||
|
||||
//之后回调
|
||||
if (appConfig.isAddFriendShipBlackAfterCallback()){
|
||||
AddFriendBlackAfterCallbackDto callbackDto = new AddFriendBlackAfterCallbackDto();
|
||||
callbackDto.setFromId(req.getFromId());
|
||||
callbackDto.setToId(req.getToId());
|
||||
callbackService.beforeCallback(req.getAppId(),
|
||||
Constants.CallbackCommand.DeleteBlack, JSONObject
|
||||
.toJSONString(callbackDto));
|
||||
}
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO checkFriendship(CheckFriendShipReq req) {
|
||||
|
||||
Map<String, Integer> result
|
||||
= req.getToIds().stream()
|
||||
.collect(Collectors.toMap(Function.identity(), s -> 0));
|
||||
|
||||
List<CheckFriendShipResp> resp = new ArrayList<>();
|
||||
|
||||
if(req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()){
|
||||
resp =imFriendShipMapper.checkFriendShip(req);
|
||||
}else {
|
||||
resp =imFriendShipMapper.checkFriendShipBoth(req);
|
||||
}
|
||||
|
||||
Map<String, Integer> collect = resp.stream()
|
||||
.collect(Collectors.toMap(CheckFriendShipResp::getToId
|
||||
, CheckFriendShipResp::getStatus));
|
||||
|
||||
for (String toId : result.keySet()){
|
||||
if(!collect.containsKey(toId)){
|
||||
CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp();
|
||||
checkFriendShipResp.setFromId(req.getFromId());
|
||||
checkFriendShipResp.setToId(toId);
|
||||
checkFriendShipResp.setStatus(result.get(toId));
|
||||
resp.add(checkFriendShipResp);
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.lld.im.service.friendship.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.lld.im.codec.pack.friendship.AddFriendGroupMemberPack;
|
||||
import com.lld.im.codec.pack.friendship.DeleteFriendGroupMemberPack;
|
||||
import com.lld.im.codec.proto.Message;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.enums.command.FriendshipEventCommand;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity;
|
||||
import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMemberMapper;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupService;
|
||||
import com.lld.im.service.user.dao.ImUserDataEntity;
|
||||
import com.lld.im.service.user.service.ImUserService;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Service
|
||||
public class ImFriendShipGroupMemberServiceImpl
|
||||
implements ImFriendShipGroupMemberService {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupMemberMapper imFriendShipGroupMemberMapper;
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupService imFriendShipGroupService;
|
||||
|
||||
@Autowired
|
||||
ImUserService imUserService;
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupMemberService thisService;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req) {
|
||||
|
||||
ResponseVO<ImFriendShipGroupEntity> group = imFriendShipGroupService
|
||||
.getGroup(req.getFromId(),req.getGroupName(),req.getAppId());
|
||||
if(!group.isOk()){
|
||||
return group;
|
||||
}
|
||||
|
||||
List<String> successId = new ArrayList<>();
|
||||
for (String toId : req.getToIds()) {
|
||||
ResponseVO<ImUserDataEntity> singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId());
|
||||
if(singleUserInfo.isOk()){
|
||||
int i = thisService.doAddGroupMember(group.getData().getGroupId(), toId);
|
||||
if(i == 1){
|
||||
successId.add(toId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Long seq = imFriendShipGroupService.updateSeq(req.getFromId(), req.getGroupName(), req.getAppId());
|
||||
AddFriendGroupMemberPack pack = new AddFriendGroupMemberPack();
|
||||
pack.setFromId(req.getFromId());
|
||||
pack.setGroupName(req.getGroupName());
|
||||
pack.setToIds(successId);
|
||||
pack.setSequence(seq);
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(), FriendshipEventCommand.FRIEND_GROUP_MEMBER_ADD,
|
||||
pack,new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
|
||||
|
||||
return ResponseVO.successResponse(successId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req) {
|
||||
ResponseVO<ImFriendShipGroupEntity> group = imFriendShipGroupService
|
||||
.getGroup(req.getFromId(),req.getGroupName(),req.getAppId());
|
||||
if(!group.isOk()){
|
||||
return group;
|
||||
}
|
||||
|
||||
List<String> successId = new ArrayList<>();
|
||||
for (String toId : req.getToIds()) {
|
||||
ResponseVO<ImUserDataEntity> singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId());
|
||||
if(singleUserInfo.isOk()){
|
||||
int i = deleteGroupMember(group.getData().getGroupId(), toId);
|
||||
if(i == 1){
|
||||
successId.add(toId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Long seq = imFriendShipGroupService.updateSeq(req.getFromId(), req.getGroupName(), req.getAppId());
|
||||
DeleteFriendGroupMemberPack pack = new DeleteFriendGroupMemberPack();
|
||||
pack.setFromId(req.getFromId());
|
||||
pack.setGroupName(req.getGroupName());
|
||||
pack.setToIds(successId);
|
||||
pack.setSequence(seq);
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(), FriendshipEventCommand.FRIEND_GROUP_MEMBER_DELETE,
|
||||
pack,new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
|
||||
return ResponseVO.successResponse(successId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doAddGroupMember(Long groupId, String toId) {
|
||||
ImFriendShipGroupMemberEntity imFriendShipGroupMemberEntity = new ImFriendShipGroupMemberEntity();
|
||||
imFriendShipGroupMemberEntity.setGroupId(groupId);
|
||||
imFriendShipGroupMemberEntity.setToId(toId);
|
||||
|
||||
try {
|
||||
int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity);
|
||||
return insert;
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int deleteGroupMember(Long groupId, String toId) {
|
||||
QueryWrapper<ImFriendShipGroupMemberEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("group_id",groupId);
|
||||
queryWrapper.eq("to_id",toId);
|
||||
|
||||
try {
|
||||
int delete = imFriendShipGroupMemberMapper.delete(queryWrapper);
|
||||
// int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity);
|
||||
return delete;
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clearGroupMember(Long groupId) {
|
||||
QueryWrapper<ImFriendShipGroupMemberEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_id",groupId);
|
||||
int delete = imFriendShipGroupMemberMapper.delete(query);
|
||||
return delete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package com.lld.im.service.friendship.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.lld.im.codec.pack.friendship.AddFriendGroupPack;
|
||||
import com.lld.im.codec.pack.friendship.DeleteFriendGroupPack;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.DelFlagEnum;
|
||||
import com.lld.im.common.enums.FriendShipErrorCode;
|
||||
import com.lld.im.common.enums.command.FriendshipEventCommand;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity;
|
||||
import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMapper;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq;
|
||||
import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq;
|
||||
import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipGroupService;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.user.service.ImUserService;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import com.lld.im.service.utils.WriteUserSeq;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class ImFriendShipGroupServiceImpl implements ImFriendShipGroupService {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupMapper imFriendShipGroupMapper;
|
||||
|
||||
@Autowired
|
||||
ImFriendShipGroupMemberService imFriendShipGroupMemberService;
|
||||
|
||||
@Autowired
|
||||
ImUserService imUserService;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Autowired
|
||||
WriteUserSeq writeUserSeq;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO addGroup(AddFriendShipGroupReq req) {
|
||||
|
||||
QueryWrapper<ImFriendShipGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_name", req.getGroupName());
|
||||
query.eq("app_id", req.getAppId());
|
||||
query.eq("from_id", req.getFromId());
|
||||
query.eq("del_flag", DelFlagEnum.NORMAL.getCode());
|
||||
|
||||
ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query);
|
||||
|
||||
if (entity != null) {
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST);
|
||||
}
|
||||
|
||||
//写入db
|
||||
ImFriendShipGroupEntity insert = new ImFriendShipGroupEntity();
|
||||
insert.setAppId(req.getAppId());
|
||||
insert.setCreateTime(System.currentTimeMillis());
|
||||
insert.setDelFlag(DelFlagEnum.NORMAL.getCode());
|
||||
insert.setGroupName(req.getGroupName());
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.FriendshipGroup);
|
||||
insert.setSequence(seq);
|
||||
insert.setFromId(req.getFromId());
|
||||
try {
|
||||
int insert1 = imFriendShipGroupMapper.insert(insert);
|
||||
|
||||
if (insert1 != 1) {
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_CREATE_ERROR);
|
||||
}
|
||||
if (insert1 == 1 && CollectionUtil.isNotEmpty(req.getToIds())) {
|
||||
AddFriendShipGroupMemberReq addFriendShipGroupMemberReq = new AddFriendShipGroupMemberReq();
|
||||
addFriendShipGroupMemberReq.setFromId(req.getFromId());
|
||||
addFriendShipGroupMemberReq.setGroupName(req.getGroupName());
|
||||
addFriendShipGroupMemberReq.setToIds(req.getToIds());
|
||||
addFriendShipGroupMemberReq.setAppId(req.getAppId());
|
||||
imFriendShipGroupMemberService.addGroupMember(addFriendShipGroupMemberReq);
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
} catch (DuplicateKeyException e) {
|
||||
e.getStackTrace();
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST);
|
||||
}
|
||||
|
||||
AddFriendGroupPack addFriendGropPack = new AddFriendGroupPack();
|
||||
addFriendGropPack.setFromId(req.getFromId());
|
||||
addFriendGropPack.setGroupName(req.getGroupName());
|
||||
addFriendGropPack.setSequence(seq);
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(), FriendshipEventCommand.FRIEND_GROUP_ADD,
|
||||
addFriendGropPack,new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
|
||||
//写入seq
|
||||
writeUserSeq.writeUserSeq(req.getAppId(), req.getFromId(), Constants.SeqConstants.FriendshipGroup, seq);
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO deleteGroup(DeleteFriendShipGroupReq req) {
|
||||
|
||||
for (String groupName : req.getGroupName()) {
|
||||
QueryWrapper<ImFriendShipGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_name", groupName);
|
||||
query.eq("app_id", req.getAppId());
|
||||
query.eq("from_id", req.getFromId());
|
||||
query.eq("del_flag", DelFlagEnum.NORMAL.getCode());
|
||||
|
||||
ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query);
|
||||
|
||||
if (entity != null) {
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.FriendshipGroup);
|
||||
ImFriendShipGroupEntity update = new ImFriendShipGroupEntity();
|
||||
update.setSequence(seq);
|
||||
update.setGroupId(entity.getGroupId());
|
||||
update.setDelFlag(DelFlagEnum.DELETE.getCode());
|
||||
imFriendShipGroupMapper.updateById(update);
|
||||
imFriendShipGroupMemberService.clearGroupMember(entity.getGroupId());
|
||||
DeleteFriendGroupPack deleteFriendGroupPack = new DeleteFriendGroupPack();
|
||||
deleteFriendGroupPack.setFromId(req.getFromId());
|
||||
deleteFriendGroupPack.setGroupName(groupName);
|
||||
deleteFriendGroupPack.setSequence(seq);
|
||||
//TCP通知
|
||||
messageProducer.sendToUserExceptClient(req.getFromId(), FriendshipEventCommand.FRIEND_GROUP_DELETE,
|
||||
deleteFriendGroupPack,new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
|
||||
//写入seq
|
||||
writeUserSeq.writeUserSeq(req.getAppId(), req.getFromId(), Constants.SeqConstants.FriendshipGroup, seq);
|
||||
}
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO getGroup(String fromId, String groupName, Integer appId) {
|
||||
QueryWrapper<ImFriendShipGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_name", groupName);
|
||||
query.eq("app_id", appId);
|
||||
query.eq("from_id", fromId);
|
||||
query.eq("del_flag", DelFlagEnum.NORMAL.getCode());
|
||||
|
||||
ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query);
|
||||
if (entity == null) {
|
||||
return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_NOT_EXIST);
|
||||
}
|
||||
return ResponseVO.successResponse(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long updateSeq(String fromId, String groupName, Integer appId) {
|
||||
QueryWrapper<ImFriendShipGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_name", groupName);
|
||||
query.eq("app_id", appId);
|
||||
query.eq("from_id", fromId);
|
||||
|
||||
ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query);
|
||||
|
||||
long seq = redisSeq.doGetSeq(appId + ":" + Constants.SeqConstants.FriendshipGroup);
|
||||
|
||||
ImFriendShipGroupEntity group = new ImFriendShipGroupEntity();
|
||||
group.setGroupId(entity.getGroupId());
|
||||
group.setSequence(seq);
|
||||
imFriendShipGroupMapper.updateById(group);
|
||||
return seq;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package com.lld.im.service.friendship.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.lld.im.codec.pack.friendship.ApproverFriendRequestPack;
|
||||
import com.lld.im.codec.pack.friendship.ReadAllFriendRequestPack;
|
||||
import com.lld.im.codec.proto.Message;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.ApproverFriendRequestStatusEnum;
|
||||
import com.lld.im.common.enums.FriendShipErrorCode;
|
||||
import com.lld.im.common.enums.command.FriendshipEventCommand;
|
||||
import com.lld.im.common.exception.ApplicationException;
|
||||
import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity;
|
||||
import com.lld.im.service.friendship.dao.mapper.ImFriendShipRequestMapper;
|
||||
import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq;
|
||||
import com.lld.im.service.friendship.model.req.FriendDto;
|
||||
import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq;
|
||||
import com.lld.im.service.friendship.service.ImFriendService;
|
||||
import com.lld.im.service.friendship.service.ImFriendShipRequestService;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import com.lld.im.service.utils.WriteUserSeq;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Service
|
||||
public class ImFriendShipRequestServiceImpl implements ImFriendShipRequestService {
|
||||
|
||||
@Autowired
|
||||
ImFriendShipRequestMapper imFriendShipRequestMapper;
|
||||
|
||||
@Autowired
|
||||
ImFriendService imFriendShipService;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
@Autowired
|
||||
WriteUserSeq writeUserSeq;
|
||||
|
||||
@Override
|
||||
public ResponseVO getFriendRequest(String fromId, Integer appId) {
|
||||
|
||||
QueryWrapper<ImFriendShipRequestEntity> query = new QueryWrapper();
|
||||
query.eq("app_id", appId);
|
||||
query.eq("to_id", fromId);
|
||||
|
||||
List<ImFriendShipRequestEntity> requestList = imFriendShipRequestMapper.selectList(query);
|
||||
|
||||
return ResponseVO.successResponse(requestList);
|
||||
}
|
||||
|
||||
|
||||
//A + B
|
||||
@Override
|
||||
public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId) {
|
||||
|
||||
QueryWrapper<ImFriendShipRequestEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("app_id",appId);
|
||||
queryWrapper.eq("from_id",fromId);
|
||||
queryWrapper.eq("to_id",dto.getToId());
|
||||
ImFriendShipRequestEntity request = imFriendShipRequestMapper.selectOne(queryWrapper);
|
||||
|
||||
long seq = redisSeq.doGetSeq(appId+":"+
|
||||
Constants.SeqConstants.FriendshipRequest);
|
||||
|
||||
if(request == null){
|
||||
request = new ImFriendShipRequestEntity();
|
||||
request.setAddSource(dto.getAddSource());
|
||||
request.setAddWording(dto.getAddWording());
|
||||
request.setSequence(seq);
|
||||
request.setAppId(appId);
|
||||
request.setFromId(fromId);
|
||||
request.setToId(dto.getToId());
|
||||
request.setReadStatus(0);
|
||||
request.setApproveStatus(0);
|
||||
request.setRemark(dto.getRemark());
|
||||
request.setCreateTime(System.currentTimeMillis());
|
||||
imFriendShipRequestMapper.insert(request);
|
||||
|
||||
}else {
|
||||
//修改记录内容 和更新时间
|
||||
if(StringUtils.isNotBlank(dto.getAddSource())){
|
||||
request.setAddWording(dto.getAddWording());
|
||||
}
|
||||
if(StringUtils.isNotBlank(dto.getRemark())){
|
||||
request.setRemark(dto.getRemark());
|
||||
}
|
||||
if(StringUtils.isNotBlank(dto.getAddWording())){
|
||||
request.setAddWording(dto.getAddWording());
|
||||
}
|
||||
request.setSequence(seq);
|
||||
request.setApproveStatus(0);
|
||||
request.setReadStatus(0);
|
||||
imFriendShipRequestMapper.updateById(request);
|
||||
}
|
||||
|
||||
writeUserSeq.writeUserSeq(appId,dto.getToId(),
|
||||
Constants.SeqConstants.FriendshipRequest,seq);
|
||||
|
||||
//发送好友申请的tcp给接收方
|
||||
messageProducer.sendToUser(dto.getToId(),
|
||||
null, "", FriendshipEventCommand.FRIEND_REQUEST,
|
||||
request, appId);
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO approverFriendRequest(ApproverFriendRequestReq req) {
|
||||
|
||||
ImFriendShipRequestEntity imFriendShipRequestEntity = imFriendShipRequestMapper.selectById(req.getId());
|
||||
if(imFriendShipRequestEntity == null){
|
||||
throw new ApplicationException(FriendShipErrorCode.FRIEND_REQUEST_IS_NOT_EXIST);
|
||||
}
|
||||
|
||||
if(!req.getOperater().equals(imFriendShipRequestEntity.getToId())){
|
||||
//只能审批发给自己的好友请求
|
||||
throw new ApplicationException(FriendShipErrorCode.NOT_APPROVER_OTHER_MAN_REQUEST);
|
||||
}
|
||||
|
||||
long seq = redisSeq.doGetSeq(req.getAppId()+":"+
|
||||
Constants.SeqConstants.FriendshipRequest);
|
||||
|
||||
ImFriendShipRequestEntity update = new ImFriendShipRequestEntity();
|
||||
update.setApproveStatus(req.getStatus());
|
||||
update.setUpdateTime(System.currentTimeMillis());
|
||||
update.setSequence(seq);
|
||||
update.setId(req.getId());
|
||||
imFriendShipRequestMapper.updateById(update);
|
||||
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getOperater(),
|
||||
Constants.SeqConstants.FriendshipRequest,seq);
|
||||
|
||||
if(ApproverFriendRequestStatusEnum.AGREE.getCode() == req.getStatus()){
|
||||
//同意 ===> 去执行添加好友逻辑
|
||||
FriendDto dto = new FriendDto();
|
||||
dto.setAddSource(imFriendShipRequestEntity.getAddSource());
|
||||
dto.setAddWording(imFriendShipRequestEntity.getAddWording());
|
||||
dto.setRemark(imFriendShipRequestEntity.getRemark());
|
||||
dto.setToId(imFriendShipRequestEntity.getToId());
|
||||
ResponseVO responseVO = imFriendShipService.doAddFriend(req,imFriendShipRequestEntity.getFromId(), dto,req.getAppId());
|
||||
// if(!responseVO.isOk()){
|
||||
//// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
// return responseVO;
|
||||
// }
|
||||
if(!responseVO.isOk() && responseVO.getCode() != FriendShipErrorCode.TO_IS_YOUR_FRIEND.getCode()){
|
||||
return responseVO;
|
||||
}
|
||||
}
|
||||
|
||||
ApproverFriendRequestPack approverFriendRequestPack = new ApproverFriendRequestPack();
|
||||
approverFriendRequestPack.setId(req.getId());
|
||||
approverFriendRequestPack.setSequence(seq);
|
||||
approverFriendRequestPack.setStatus(req.getStatus());
|
||||
messageProducer.sendToUser(imFriendShipRequestEntity.getToId(),req.getClientType(),req.getImei(), FriendshipEventCommand
|
||||
.FRIEND_REQUEST_APPROVER,approverFriendRequestPack,req.getAppId());
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req) {
|
||||
QueryWrapper<ImFriendShipRequestEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id", req.getAppId());
|
||||
query.eq("to_id", req.getFromId());
|
||||
|
||||
long seq = redisSeq.doGetSeq(req.getAppId()+":"+
|
||||
Constants.SeqConstants.FriendshipRequest);
|
||||
ImFriendShipRequestEntity update = new ImFriendShipRequestEntity();
|
||||
update.setReadStatus(1);
|
||||
update.setSequence(seq);
|
||||
imFriendShipRequestMapper.update(update, query);
|
||||
writeUserSeq.writeUserSeq(req.getAppId(),req.getOperater(),
|
||||
Constants.SeqConstants.FriendshipRequest,seq);
|
||||
//TCP通知
|
||||
ReadAllFriendRequestPack readAllFriendRequestPack = new ReadAllFriendRequestPack();
|
||||
readAllFriendRequestPack.setFromId(req.getFromId());
|
||||
readAllFriendRequestPack.setSequence(seq);
|
||||
messageProducer.sendToUser(req.getFromId(),req.getClientType(),req.getImei(),FriendshipEventCommand
|
||||
.FRIEND_REQUEST_READ,readAllFriendRequestPack,req.getAppId());
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.lld.im.service.group.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
import com.lld.im.service.group.service.GroupMessageService;
|
||||
import com.lld.im.service.group.service.ImGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("v1/group")
|
||||
public class ImGroupController {
|
||||
|
||||
@Autowired
|
||||
ImGroupService groupService;
|
||||
|
||||
@Autowired
|
||||
GroupMessageService groupMessageService;
|
||||
|
||||
@RequestMapping("/importGroup")
|
||||
public ResponseVO importGroup(@RequestBody @Validated ImportGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.importGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/createGroup")
|
||||
public ResponseVO createGroup(@RequestBody @Validated CreateGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.createGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/getGroupInfo")
|
||||
public ResponseVO getGroupInfo(@RequestBody @Validated GetGroupReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return groupService.getGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
public ResponseVO update(@RequestBody @Validated UpdateGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.updateBaseGroupInfo(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/getJoinedGroup")
|
||||
public ResponseVO getJoinedGroup(@RequestBody @Validated GetJoinedGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.getJoinedGroup(req);
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/destroyGroup")
|
||||
public ResponseVO destroyGroup(@RequestBody @Validated DestroyGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.destroyGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/transferGroup")
|
||||
public ResponseVO transferGroup(@RequestBody @Validated TransferGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.transferGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/forbidSendMessage")
|
||||
public ResponseVO forbidSendMessage(@RequestBody @Validated MuteGroupReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupService.muteGroup(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/sendMessage")
|
||||
public ResponseVO sendMessage(@RequestBody @Validated SendGroupMessageReq
|
||||
req, Integer appId,
|
||||
String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return ResponseVO.successResponse(groupMessageService.send(req));
|
||||
}
|
||||
|
||||
@RequestMapping("/syncJoinedGroup")
|
||||
public ResponseVO syncJoinedGroup(@RequestBody @Validated SyncReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
return groupService.syncJoinedGroupList(req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.lld.im.service.group.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
import com.lld.im.service.group.service.ImGroupMemberService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("v1/group/member")
|
||||
public class ImGroupMemberController {
|
||||
|
||||
@Autowired
|
||||
ImGroupMemberService groupMemberService;
|
||||
|
||||
@RequestMapping("/importGroupMember")
|
||||
public ResponseVO importGroupMember(@RequestBody @Validated ImportGroupMemberReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupMemberService.importGroupMember(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
public ResponseVO addMember(@RequestBody @Validated AddGroupMemberReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupMemberService.addMember(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/remove")
|
||||
public ResponseVO removeMember(@RequestBody @Validated RemoveGroupMemberReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupMemberService.removeMember(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
public ResponseVO updateGroupMember(@RequestBody @Validated UpdateGroupMemberReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupMemberService.updateGroupMember(req);
|
||||
}
|
||||
|
||||
@RequestMapping("/speak")
|
||||
public ResponseVO speak(@RequestBody @Validated SpeaMemberReq req, Integer appId, String identifier) {
|
||||
req.setAppId(appId);
|
||||
req.setOperater(identifier);
|
||||
return groupMemberService.speak(req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.lld.im.service.group.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@TableName("im_group")
|
||||
public class ImGroupEntity {
|
||||
|
||||
@TableId(value = "group_id")
|
||||
private String groupId;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
//群主id
|
||||
private String ownerId;
|
||||
|
||||
//群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||
private Integer groupType;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||
|
||||
// 申请加群选项包括如下几种:
|
||||
// 0 表示禁止任何人申请加入
|
||||
// 1 表示需要群主或管理员审批
|
||||
// 2 表示允许无需审批自由加入群组
|
||||
private Integer applyJoinType;
|
||||
|
||||
private String introduction;//群简介
|
||||
|
||||
private String notification;//群公告
|
||||
|
||||
private String photo;//群头像
|
||||
|
||||
private Integer maxMemberCount;//群成员上限
|
||||
|
||||
private Integer status;//群状态 0正常 1解散
|
||||
|
||||
private Long sequence;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
private Long updateTime;
|
||||
|
||||
private String extra;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lld.im.service.group.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@TableName("im_group_member")
|
||||
public class ImGroupMemberEntity {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long groupMemberId;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
private String groupId;
|
||||
|
||||
//成员id
|
||||
private String memberId;
|
||||
|
||||
//群成员类型,0 普通成员, 1 管理员, 2 群主, 3 禁言,4 已经移除的成员
|
||||
private Integer role;
|
||||
|
||||
private Long speakDate;
|
||||
|
||||
//群昵称
|
||||
private String alias;
|
||||
|
||||
//加入时间
|
||||
private Long joinTime;
|
||||
|
||||
//离开时间
|
||||
private Long leaveTime;
|
||||
|
||||
private String joinType;
|
||||
|
||||
private String extra;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.lld.im.service.group.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
@TableName("im_group_message_history")
|
||||
public class ImGroupMessageHistoryEntity {
|
||||
|
||||
private Integer appId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String groupId;
|
||||
|
||||
/** messageBodyId*/
|
||||
private Long messageKey;
|
||||
/** 序列号*/
|
||||
private Long sequence;
|
||||
|
||||
private String messageRandom;
|
||||
|
||||
private Long messageTime;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.lld.im.service.group.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.group.dao.ImGroupEntity;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Repository
|
||||
public interface ImGroupMapper extends BaseMapper<ImGroupEntity> {
|
||||
|
||||
/**
|
||||
* @description 获取加入的群的最大seq
|
||||
* @author chackylee
|
||||
* @param []
|
||||
* @return java.lang.Long
|
||||
*/
|
||||
@Select(" <script> " +
|
||||
" select max(sequence) from im_group where app_id = #{appId} and group_id in " +
|
||||
"<foreach collection='groupId' index='index' item='id' separator=',' close=')' open='('>" +
|
||||
" #{id} " +
|
||||
"</foreach>" +
|
||||
" </script> ")
|
||||
Long getGroupMaxSeq(Collection<String> groupId, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.lld.im.service.group.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.group.dao.ImGroupMemberEntity;
|
||||
import com.lld.im.service.group.model.req.GroupMemberDto;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ImGroupMemberMapper extends BaseMapper<ImGroupMemberEntity> {
|
||||
|
||||
@Select("select group_id from im_group_member where app_id = #{appId} AND member_id = #{memberId} ")
|
||||
public List<String> getJoinedGroupId(Integer appId, String memberId);
|
||||
|
||||
@Select("select group_id from im_group_member where app_id = #{appId} AND member_id = #{memberId} and role != #{role}" )
|
||||
public List<String> syncJoinedGroupId(Integer appId, String memberId, int role);
|
||||
|
||||
|
||||
@Results({
|
||||
@Result(column = "member_id", property = "memberId"),
|
||||
// @Result(column = "speak_flag", property = "speakFlag"),
|
||||
@Result(column = "speak_date", property = "speakDate"),
|
||||
@Result(column = "role", property = "role"),
|
||||
@Result(column = "alias", property = "alias"),
|
||||
@Result(column = "join_time", property = "joinTime"),
|
||||
@Result(column = "join_type", property = "joinType")
|
||||
})
|
||||
@Select("select " +
|
||||
" member_id, " +
|
||||
// " speak_flag, " +
|
||||
" speak_date, " +
|
||||
" role, " +
|
||||
" alias, " +
|
||||
" join_time ," +
|
||||
" join_type " +
|
||||
" from im_group_member where app_id = #{appId} AND group_id = #{groupId} ")
|
||||
public List<GroupMemberDto> getGroupMember(Integer appId, String groupId);
|
||||
|
||||
@Select("select " +
|
||||
" member_id " +
|
||||
" from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role != 3")
|
||||
public List<String> getGroupMemberId(Integer appId, String groupId);
|
||||
|
||||
|
||||
@Results({
|
||||
@Result(column = "member_id", property = "memberId"),
|
||||
// @Result(column = "speak_flag", property = "speakFlag"),
|
||||
@Result(column = "role", property = "role")
|
||||
// @Result(column = "alias", property = "alias"),
|
||||
// @Result(column = "join_time", property = "joinTime"),
|
||||
// @Result(column = "join_type", property = "joinType")
|
||||
})
|
||||
@Select("select " +
|
||||
" member_id, " +
|
||||
// " speak_flag, " +
|
||||
" role " +
|
||||
// " alias, " +
|
||||
// " join_time ," +
|
||||
// " join_type " +
|
||||
" from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role in (1,2) ")
|
||||
public List<GroupMemberDto> getGroupManager(String groupId, Integer appId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.lld.im.service.group.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.group.dao.ImGroupMessageHistoryEntity;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ImGroupMessageHistoryMapper extends BaseMapper<ImGroupMessageHistoryEntity> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.group.model.callback;
|
||||
|
||||
import com.lld.im.service.group.model.resp.AddMemberResp;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class AddMemberAfterCallback {
|
||||
private String groupId;
|
||||
private Integer groupType;
|
||||
private String operater;
|
||||
private List<AddMemberResp> memberId;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lld.im.service.group.model.callback;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class DestroyGroupCallbackDto {
|
||||
|
||||
private String groupId;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class AddGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
@NotEmpty(message = "群成员不能为空")
|
||||
private List<GroupMemberDto> members;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class CreateGroupReq extends RequestBase {
|
||||
|
||||
private String groupId;
|
||||
//群主id
|
||||
private String ownerId;
|
||||
|
||||
//群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||
private Integer groupType;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||
|
||||
private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。
|
||||
|
||||
private String introduction;//群简介
|
||||
|
||||
private String notification;//群公告
|
||||
|
||||
private String photo;//群头像
|
||||
|
||||
private Integer MaxMemberCount;
|
||||
|
||||
private List<GroupMemberDto> member;
|
||||
|
||||
private String extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class DestroyGroupReq extends RequestBase {
|
||||
|
||||
@NotNull(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetGroupReq extends RequestBase {
|
||||
|
||||
private String groupId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetJoinedGroupReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "用户id不能为空")
|
||||
private String memberId;
|
||||
|
||||
//群类型
|
||||
private List<Integer> groupType;
|
||||
|
||||
//单次拉取的群组数量,如果不填代表所有群组
|
||||
private Integer limit;
|
||||
|
||||
//第几页
|
||||
private Integer offset;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetRoleInGroupReq extends RequestBase {
|
||||
|
||||
private String groupId;
|
||||
|
||||
private List<String> memberId;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class GroupMemberDto {
|
||||
|
||||
private String memberId;
|
||||
|
||||
private String alias;
|
||||
|
||||
private Integer role;//群成员类型,0 普通成员, 1 管理员, 2 群主, 3 已经移除的成员,当修改群成员信息时,只能取值0/1,其他值由其他接口实现,暂不支持3
|
||||
|
||||
// private Integer speakFlag;
|
||||
|
||||
private Long speakDate;
|
||||
|
||||
private String joinType;
|
||||
|
||||
private Long joinTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class ImportGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
private List<GroupMemberDto> members;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class ImportGroupReq extends RequestBase {
|
||||
|
||||
private String groupId;
|
||||
//群主id
|
||||
private String ownerId;
|
||||
|
||||
//群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||
private Integer groupType;
|
||||
|
||||
@NotBlank(message = "群名称不能为空")
|
||||
private String groupName;
|
||||
|
||||
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||
|
||||
private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。
|
||||
|
||||
private String introduction;//群简介
|
||||
|
||||
private String notification;//群公告
|
||||
|
||||
private String photo;//群头像
|
||||
|
||||
private Integer MaxMemberCount;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
private String extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class MuteGroupReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "groupId不能为空")
|
||||
private String groupId;
|
||||
|
||||
@NotNull(message = "mute不能为空")
|
||||
private Integer mute;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class RemoveGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
private String memberId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class SendGroupMessageReq extends RequestBase {
|
||||
|
||||
//客户端传的messageId
|
||||
private String messageId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String groupId;
|
||||
|
||||
private int messageRandom;
|
||||
|
||||
private long messageTime;
|
||||
|
||||
private String messageBody;
|
||||
/**
|
||||
* 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加
|
||||
*/
|
||||
private int badgeMode;
|
||||
|
||||
private Long messageLifeTime;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class SpeaMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
@NotBlank(message = "memberId不能为空")
|
||||
private String memberId;
|
||||
|
||||
//禁言时间,单位毫秒
|
||||
@NotNull(message = "禁言时间不能为空")
|
||||
private Long speakDate;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
@Data
|
||||
public class TransferGroupReq extends RequestBase {
|
||||
|
||||
@NotNull(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
private String ownerId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class UpdateGroupMemberReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
@NotBlank(message = "memberId不能为空")
|
||||
private String memberId;
|
||||
|
||||
private String alias;
|
||||
|
||||
private Integer role;
|
||||
|
||||
private String extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lld.im.service.group.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class UpdateGroupReq extends RequestBase {
|
||||
|
||||
@NotBlank(message = "群id不能为空")
|
||||
private String groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||
|
||||
private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。
|
||||
|
||||
private String introduction;//群简介
|
||||
|
||||
private String notification;//群公告
|
||||
|
||||
private String photo;//群头像
|
||||
|
||||
private Integer maxMemberCount;//群成员上限
|
||||
|
||||
private String extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.group.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class AddMemberResp {
|
||||
|
||||
private String memberId;
|
||||
|
||||
// 加人结果:0 为成功;1 为失败;2 为已经是群成员
|
||||
private Integer result;
|
||||
|
||||
private String resultMessage;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.lld.im.service.group.model.resp;
|
||||
|
||||
import com.lld.im.service.group.model.req.GroupMemberDto;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetGroupResp {
|
||||
|
||||
private String groupId;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
//群主id
|
||||
private String ownerId;
|
||||
|
||||
//群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||
private Integer groupType;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。
|
||||
|
||||
// 申请加群选项包括如下几种:
|
||||
// 0 表示禁止任何人申请加入
|
||||
// 1 表示需要群主或管理员审批
|
||||
// 2 表示允许无需审批自由加入群组
|
||||
private Integer applyJoinType;
|
||||
|
||||
private Integer privateChat; //是否禁止私聊,0 允许群成员发起私聊;1 不允许群成员发起私聊。
|
||||
|
||||
private String introduction;//群简介
|
||||
|
||||
private String notification;//群公告
|
||||
|
||||
private String photo;//群头像
|
||||
|
||||
private Integer maxMemberCount;//群成员上限
|
||||
|
||||
private Integer status;//群状态 0正常 1解散
|
||||
|
||||
private List<GroupMemberDto> memberList;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lld.im.service.group.model.resp;
|
||||
|
||||
import com.lld.im.service.group.dao.ImGroupEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetJoinedGroupResp {
|
||||
|
||||
private Integer totalCount;
|
||||
|
||||
private List<ImGroupEntity> groupList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.lld.im.service.group.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class GetRoleInGroupResp {
|
||||
|
||||
private Long groupMemberId;
|
||||
|
||||
private String memberId;
|
||||
|
||||
private Integer role;
|
||||
|
||||
private Long speakDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.lld.im.service.group.mq;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.command.GroupEventCommand;
|
||||
import com.lld.im.common.enums.command.MessageCommand;
|
||||
import com.lld.im.common.model.message.GroupChatMessageContent;
|
||||
import com.lld.im.common.model.message.MessageReadedContent;
|
||||
import com.lld.im.service.group.service.GroupMessageService;
|
||||
import com.lld.im.service.message.service.MessageSyncService;
|
||||
import com.lld.im.service.message.service.P2PMessageService;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.Exchange;
|
||||
import org.springframework.amqp.rabbit.annotation.Queue;
|
||||
import org.springframework.amqp.rabbit.annotation.QueueBinding;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.support.AmqpHeaders;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.handler.annotation.Headers;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Component
|
||||
public class GroupChatOperateReceiver {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(GroupChatOperateReceiver.class);
|
||||
|
||||
// @Autowired
|
||||
// P2PMessageService p2PMessageService;
|
||||
@Autowired
|
||||
GroupMessageService groupMessageService;
|
||||
|
||||
@Autowired
|
||||
MessageSyncService messageSyncService;
|
||||
|
||||
@RabbitListener(
|
||||
bindings = @QueueBinding(
|
||||
value = @Queue(value = Constants.RabbitConstants.Im2GroupService,durable = "true"),
|
||||
exchange = @Exchange(value = Constants.RabbitConstants.Im2GroupService,durable = "true")
|
||||
),concurrency = "1"
|
||||
)
|
||||
public void onChatMessage(@Payload Message message,
|
||||
@Headers Map<String,Object> headers,
|
||||
Channel channel) throws Exception {
|
||||
String msg = new String(message.getBody(),"utf-8");
|
||||
logger.info("CHAT MSG FORM QUEUE ::: {}", msg);
|
||||
Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
|
||||
try {
|
||||
JSONObject jsonObject = JSON.parseObject(msg);
|
||||
Integer command = jsonObject.getInteger("command");
|
||||
if(command.equals(GroupEventCommand.MSG_GROUP.getCommand())){
|
||||
//处理消息
|
||||
GroupChatMessageContent messageContent
|
||||
= jsonObject.toJavaObject(GroupChatMessageContent.class);
|
||||
// p2PMessageService.process(messageContent);
|
||||
groupMessageService.process(messageContent);
|
||||
}else if (command.equals(GroupEventCommand.MSG_GROUP_READED.getCommand())) {
|
||||
MessageReadedContent messageReaded = JSON.parseObject(msg, new TypeReference<MessageReadedContent>() {
|
||||
}.getType());
|
||||
messageSyncService.groupReadMark(messageReaded);
|
||||
}
|
||||
channel.basicAck(deliveryTag, false);
|
||||
}catch (Exception e){
|
||||
logger.error("处理消息出现异常:{}", e.getMessage());
|
||||
logger.error("RMQ_CHAT_TRAN_ERROR", e);
|
||||
logger.error("NACK_MSG:{}", msg);
|
||||
//第一个false 表示不批量拒绝,第二个false表示不重回队列
|
||||
channel.basicNack(deliveryTag, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.lld.im.service.group.service;
|
||||
|
||||
import com.lld.im.codec.pack.message.ChatMessageAck;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.command.GroupEventCommand;
|
||||
import com.lld.im.common.enums.command.MessageCommand;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.common.model.message.GroupChatMessageContent;
|
||||
import com.lld.im.common.model.message.MessageContent;
|
||||
import com.lld.im.common.model.message.OfflineMessageContent;
|
||||
import com.lld.im.service.group.model.req.SendGroupMessageReq;
|
||||
import com.lld.im.service.message.model.resp.SendMessageResp;
|
||||
import com.lld.im.service.message.service.CheckSendMessageService;
|
||||
import com.lld.im.service.message.service.MessageStoreService;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.utils.MessageProducer;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class GroupMessageService {
|
||||
|
||||
@Autowired
|
||||
CheckSendMessageService checkSendMessageService;
|
||||
|
||||
@Autowired
|
||||
MessageProducer messageProducer;
|
||||
|
||||
@Autowired
|
||||
ImGroupMemberService imGroupMemberService;
|
||||
|
||||
@Autowired
|
||||
MessageStoreService messageStoreService;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
private final ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
{
|
||||
AtomicInteger num = new AtomicInteger(0);
|
||||
threadPoolExecutor = new ThreadPoolExecutor(8, 8, 60, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(1000), new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setDaemon(true);
|
||||
thread.setName("message-group-thread-" + num.getAndIncrement());
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void process(GroupChatMessageContent messageContent){
|
||||
String fromId = messageContent.getFromId();
|
||||
String groupId = messageContent.getGroupId();
|
||||
Integer appId = messageContent.getAppId();
|
||||
//前置校验
|
||||
//这个用户是否被禁言 是否被禁用
|
||||
//发送方和接收方是否是好友
|
||||
GroupChatMessageContent messageFromMessageIdCache = messageStoreService.getMessageFromMessageIdCache(messageContent.getAppId(),
|
||||
messageContent.getMessageId(), GroupChatMessageContent.class);
|
||||
if(messageFromMessageIdCache != null){
|
||||
threadPoolExecutor.execute(() ->{
|
||||
//1.回ack成功给自己
|
||||
ack(messageContent,ResponseVO.successResponse());
|
||||
//2.发消息给同步在线端
|
||||
syncToSender(messageContent,messageContent);
|
||||
//3.发消息给对方在线端
|
||||
dispatchMessage(messageContent);
|
||||
});
|
||||
}
|
||||
long seq = redisSeq.doGetSeq(messageContent.getAppId() + ":" + Constants.SeqConstants.GroupMessage
|
||||
+ messageContent.getGroupId());
|
||||
messageContent.setMessageSequence(seq);
|
||||
threadPoolExecutor.execute(() ->{
|
||||
messageStoreService.storeGroupMessage(messageContent);
|
||||
|
||||
List<String> groupMemberId = imGroupMemberService.getGroupMemberId(messageContent.getGroupId(),
|
||||
messageContent.getAppId());
|
||||
messageContent.setMemberId(groupMemberId);
|
||||
|
||||
OfflineMessageContent offlineMessageContent = new OfflineMessageContent();
|
||||
BeanUtils.copyProperties(messageContent,offlineMessageContent);
|
||||
offlineMessageContent.setToId(messageContent.getGroupId());
|
||||
messageStoreService.storeGroupOfflineMessage(offlineMessageContent,groupMemberId);
|
||||
|
||||
//1.回ack成功给自己
|
||||
ack(messageContent,ResponseVO.successResponse());
|
||||
//2.发消息给同步在线端
|
||||
syncToSender(messageContent,messageContent);
|
||||
//3.发消息给对方在线端
|
||||
dispatchMessage(messageContent);
|
||||
|
||||
messageStoreService.setMessageFromMessageIdCache(messageContent.getAppId(),
|
||||
messageContent.getMessageId(),messageContent);
|
||||
});
|
||||
}
|
||||
|
||||
private void dispatchMessage(GroupChatMessageContent messageContent){
|
||||
for (String memberId : messageContent.getMemberId()) {
|
||||
if(!memberId.equals(messageContent.getFromId())){
|
||||
messageProducer.sendToUser(memberId,
|
||||
GroupEventCommand.MSG_GROUP,
|
||||
messageContent,messageContent.getAppId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ack(MessageContent messageContent,ResponseVO responseVO){
|
||||
|
||||
ChatMessageAck chatMessageAck = new ChatMessageAck(messageContent.getMessageId());
|
||||
responseVO.setData(chatMessageAck);
|
||||
//發消息
|
||||
messageProducer.sendToUser(messageContent.getFromId(),
|
||||
GroupEventCommand.GROUP_MSG_ACK,
|
||||
responseVO,messageContent
|
||||
);
|
||||
}
|
||||
|
||||
private void syncToSender(GroupChatMessageContent messageContent, ClientInfo clientInfo){
|
||||
messageProducer.sendToUserExceptClient(messageContent.getFromId(),
|
||||
GroupEventCommand.MSG_GROUP,messageContent,messageContent);
|
||||
}
|
||||
|
||||
private ResponseVO imServerPermissionCheck(String fromId, String toId,Integer appId){
|
||||
ResponseVO responseVO = checkSendMessageService
|
||||
.checkGroupMessage(fromId, toId,appId);
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
public SendMessageResp send(SendGroupMessageReq req) {
|
||||
|
||||
SendMessageResp sendMessageResp = new SendMessageResp();
|
||||
GroupChatMessageContent message = new GroupChatMessageContent();
|
||||
BeanUtils.copyProperties(req,message);
|
||||
|
||||
messageStoreService.storeGroupMessage(message);
|
||||
|
||||
sendMessageResp.setMessageKey(message.getMessageKey());
|
||||
sendMessageResp.setMessageTime(System.currentTimeMillis());
|
||||
//2.发消息给同步在线端
|
||||
syncToSender(message,message);
|
||||
//3.发消息给对方在线端
|
||||
dispatchMessage(message);
|
||||
|
||||
return sendMessageResp;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lld.im.service.group.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
import com.lld.im.service.group.model.resp.GetRoleInGroupResp;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface ImGroupMemberService {
|
||||
|
||||
public ResponseVO importGroupMember(ImportGroupMemberReq req);
|
||||
|
||||
public ResponseVO addMember(AddGroupMemberReq req);
|
||||
|
||||
public ResponseVO removeMember(RemoveGroupMemberReq req);
|
||||
|
||||
public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto);
|
||||
|
||||
public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId);
|
||||
|
||||
public ResponseVO<GetRoleInGroupResp> getRoleInGroupOne(String groupId, String memberId, Integer appId);
|
||||
|
||||
public ResponseVO<Collection<String>> getMemberJoinedGroup(GetJoinedGroupReq req);
|
||||
|
||||
public ResponseVO<List<GroupMemberDto>> getGroupMember(String groupId, Integer appId);
|
||||
|
||||
public List<String> getGroupMemberId(String groupId, Integer appId);
|
||||
|
||||
public List<GroupMemberDto> getGroupManager(String groupId, Integer appId);
|
||||
|
||||
public ResponseVO updateGroupMember(UpdateGroupMemberReq req);
|
||||
|
||||
public ResponseVO transferGroupMember(String owner, String groupId, Integer appId);
|
||||
|
||||
public ResponseVO speak(SpeaMemberReq req);
|
||||
|
||||
ResponseVO<Collection<String>> syncMemberJoinedGroup(String operater, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.lld.im.service.group.service;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.service.group.dao.ImGroupEntity;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface ImGroupService {
|
||||
|
||||
public ResponseVO importGroup(ImportGroupReq req);
|
||||
|
||||
public ResponseVO createGroup(CreateGroupReq req);
|
||||
|
||||
public ResponseVO updateBaseGroupInfo(UpdateGroupReq req);
|
||||
|
||||
public ResponseVO getJoinedGroup(GetJoinedGroupReq req);
|
||||
|
||||
public ResponseVO destroyGroup(DestroyGroupReq req);
|
||||
|
||||
public ResponseVO transferGroup(TransferGroupReq req);
|
||||
|
||||
public ResponseVO<ImGroupEntity> getGroup(String groupId, Integer appId);
|
||||
|
||||
public ResponseVO getGroup(GetGroupReq req);
|
||||
|
||||
public ResponseVO muteGroup(MuteGroupReq req);
|
||||
|
||||
ResponseVO syncJoinedGroupList(SyncReq req);
|
||||
|
||||
Long getUserGroupMaxSeq(String userId, Integer appId);
|
||||
}
|
||||
@@ -0,0 +1,626 @@
|
||||
package com.lld.im.service.group.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.lld.im.codec.pack.group.AddGroupMemberPack;
|
||||
import com.lld.im.codec.pack.group.GroupMemberSpeakPack;
|
||||
import com.lld.im.codec.pack.group.RemoveGroupMemberPack;
|
||||
import com.lld.im.codec.pack.group.UpdateGroupMemberPack;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.GroupErrorCode;
|
||||
import com.lld.im.common.enums.GroupMemberRoleEnum;
|
||||
import com.lld.im.common.enums.GroupStatusEnum;
|
||||
import com.lld.im.common.enums.GroupTypeEnum;
|
||||
import com.lld.im.common.enums.command.GroupEventCommand;
|
||||
import com.lld.im.common.exception.ApplicationException;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.service.group.dao.ImGroupEntity;
|
||||
import com.lld.im.service.group.dao.ImGroupMemberEntity;
|
||||
import com.lld.im.service.group.dao.mapper.ImGroupMemberMapper;
|
||||
import com.lld.im.service.group.model.callback.AddMemberAfterCallback;
|
||||
import com.lld.im.service.group.model.callback.DestroyGroupCallbackDto;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
import com.lld.im.service.group.model.resp.AddMemberResp;
|
||||
import com.lld.im.service.group.model.resp.GetRoleInGroupResp;
|
||||
import com.lld.im.service.group.service.ImGroupMemberService;
|
||||
import com.lld.im.service.group.service.ImGroupService;
|
||||
import com.lld.im.service.user.dao.ImUserDataEntity;
|
||||
import com.lld.im.service.user.service.ImUserService;
|
||||
import com.lld.im.service.utils.CallbackService;
|
||||
import com.lld.im.service.utils.GroupMessageProducer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ImGroupMemberServiceImpl implements ImGroupMemberService {
|
||||
|
||||
@Autowired
|
||||
ImGroupMemberMapper imGroupMemberMapper;
|
||||
|
||||
@Autowired
|
||||
ImGroupService groupService;
|
||||
|
||||
@Autowired
|
||||
ImGroupMemberService groupMemberService;
|
||||
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Autowired
|
||||
CallbackService callbackService;
|
||||
|
||||
@Autowired
|
||||
ImUserService imUserService;
|
||||
|
||||
@Autowired
|
||||
GroupMessageProducer groupMessageProducer;
|
||||
|
||||
@Override
|
||||
public ResponseVO importGroupMember(ImportGroupMemberReq req) {
|
||||
|
||||
List<AddMemberResp> resp = new ArrayList<>();
|
||||
|
||||
ResponseVO<ImGroupEntity> groupResp = groupService.getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!groupResp.isOk()) {
|
||||
return groupResp;
|
||||
}
|
||||
|
||||
for (GroupMemberDto memberId :
|
||||
req.getMembers()) {
|
||||
ResponseVO responseVO = null;
|
||||
try {
|
||||
responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
responseVO = ResponseVO.errorResponse();
|
||||
}
|
||||
AddMemberResp addMemberResp = new AddMemberResp();
|
||||
addMemberResp.setMemberId(memberId.getMemberId());
|
||||
if (responseVO.isOk()) {
|
||||
addMemberResp.setResult(0);
|
||||
} else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) {
|
||||
addMemberResp.setResult(2);
|
||||
} else {
|
||||
addMemberResp.setResult(1);
|
||||
}
|
||||
resp.add(addMemberResp);
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description: 添加群成员,内部调用
|
||||
* @author lld
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto) {
|
||||
|
||||
ResponseVO<ImUserDataEntity> singleUserInfo = imUserService.getSingleUserInfo(dto.getMemberId(), appId);
|
||||
if(!singleUserInfo.isOk()){
|
||||
return singleUserInfo;
|
||||
}
|
||||
|
||||
if (dto.getRole() != null && GroupMemberRoleEnum.OWNER.getCode() == dto.getRole()) {
|
||||
QueryWrapper<ImGroupMemberEntity> queryOwner = new QueryWrapper<>();
|
||||
queryOwner.eq("group_id", groupId);
|
||||
queryOwner.eq("app_id", appId);
|
||||
queryOwner.eq("role", GroupMemberRoleEnum.OWNER.getCode());
|
||||
Integer ownerNum = imGroupMemberMapper.selectCount(queryOwner);
|
||||
if (ownerNum > 0) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_HAVE_OWNER);
|
||||
}
|
||||
}
|
||||
|
||||
QueryWrapper<ImGroupMemberEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_id", groupId);
|
||||
query.eq("app_id", appId);
|
||||
query.eq("member_id", dto.getMemberId());
|
||||
ImGroupMemberEntity memberDto = imGroupMemberMapper.selectOne(query);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (memberDto == null) {
|
||||
//初次加群
|
||||
memberDto = new ImGroupMemberEntity();
|
||||
BeanUtils.copyProperties(dto, memberDto);
|
||||
memberDto.setGroupId(groupId);
|
||||
memberDto.setAppId(appId);
|
||||
memberDto.setJoinTime(now);
|
||||
int insert = imGroupMemberMapper.insert(memberDto);
|
||||
if (insert == 1) {
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR);
|
||||
} else if (GroupMemberRoleEnum.LEAVE.getCode() == memberDto.getRole()) {
|
||||
//重新进群
|
||||
memberDto = new ImGroupMemberEntity();
|
||||
BeanUtils.copyProperties(dto, memberDto);
|
||||
memberDto.setJoinTime(now);
|
||||
int update = imGroupMemberMapper.update(memberDto, query);
|
||||
if (update == 1) {
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR);
|
||||
}
|
||||
|
||||
return ResponseVO.errorResponse(GroupErrorCode.USER_IS_JOINED_GROUP);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description: 删除群成员,内部调用
|
||||
* @author lld
|
||||
*/
|
||||
@Override
|
||||
public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId) {
|
||||
|
||||
ResponseVO<ImUserDataEntity> singleUserInfo = imUserService.getSingleUserInfo(memberId, appId);
|
||||
if(!singleUserInfo.isOk()){
|
||||
return singleUserInfo;
|
||||
}
|
||||
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = getRoleInGroupOne(groupId, memberId, appId);
|
||||
if (!roleInGroupOne.isOk()) {
|
||||
return roleInGroupOne;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = roleInGroupOne.getData();
|
||||
ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity();
|
||||
imGroupMemberEntity.setRole(GroupMemberRoleEnum.LEAVE.getCode());
|
||||
imGroupMemberEntity.setLeaveTime(System.currentTimeMillis());
|
||||
imGroupMemberEntity.setGroupMemberId(data.getGroupMemberId());
|
||||
imGroupMemberMapper.updateById(imGroupMemberEntity);
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [groupId, memberId, appId]
|
||||
* @return com.lld.im.common.ResponseVO<com.lld.im.service.group.model.resp.GetRoleInGroupResp>
|
||||
* @description 查询用户在群内的角色
|
||||
* @author chackylee
|
||||
*/
|
||||
@Override
|
||||
public ResponseVO<GetRoleInGroupResp> getRoleInGroupOne(String groupId, String memberId, Integer appId) {
|
||||
|
||||
GetRoleInGroupResp resp = new GetRoleInGroupResp();
|
||||
|
||||
QueryWrapper<ImGroupMemberEntity> queryOwner = new QueryWrapper<>();
|
||||
queryOwner.eq("group_id", groupId);
|
||||
queryOwner.eq("app_id", appId);
|
||||
queryOwner.eq("member_id", memberId);
|
||||
|
||||
ImGroupMemberEntity imGroupMemberEntity = imGroupMemberMapper.selectOne(queryOwner);
|
||||
if (imGroupMemberEntity == null || imGroupMemberEntity.getRole() == GroupMemberRoleEnum.LEAVE.getCode()) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.MEMBER_IS_NOT_JOINED_GROUP);
|
||||
}
|
||||
|
||||
resp.setSpeakDate(imGroupMemberEntity.getSpeakDate());
|
||||
resp.setGroupMemberId(imGroupMemberEntity.getGroupMemberId());
|
||||
resp.setMemberId(imGroupMemberEntity.getMemberId());
|
||||
resp.setRole(imGroupMemberEntity.getRole());
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO<Collection<String>> getMemberJoinedGroup(GetJoinedGroupReq req) {
|
||||
|
||||
if (req.getLimit() != null) {
|
||||
Page<ImGroupMemberEntity> objectPage = new Page<>(req.getOffset(), req.getLimit());
|
||||
QueryWrapper<ImGroupMemberEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id", req.getAppId());
|
||||
query.eq("member_id", req.getMemberId());
|
||||
IPage<ImGroupMemberEntity> imGroupMemberEntityPage = imGroupMemberMapper.selectPage(objectPage, query);
|
||||
|
||||
Set<String> groupId = new HashSet<>();
|
||||
List<ImGroupMemberEntity> records = imGroupMemberEntityPage.getRecords();
|
||||
records.forEach(e -> {
|
||||
groupId.add(e.getGroupId());
|
||||
});
|
||||
|
||||
return ResponseVO.successResponse(groupId);
|
||||
} else {
|
||||
return ResponseVO.successResponse(imGroupMemberMapper.getJoinedGroupId(req.getAppId(), req.getMemberId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description: 添加群成员,拉人入群的逻辑,直接进入群聊。如果是后台管理员,则直接拉入群,
|
||||
* 否则只有私有群可以调用本接口,并且群成员也可以拉人入群.只有私有群可以调用本接口
|
||||
* @author lld
|
||||
*/
|
||||
@Override
|
||||
public ResponseVO addMember(AddGroupMemberReq req) {
|
||||
|
||||
List<AddMemberResp> resp = new ArrayList<>();
|
||||
|
||||
boolean isAdmin = false;
|
||||
ResponseVO<ImGroupEntity> groupResp = groupService.getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!groupResp.isOk()) {
|
||||
return groupResp;
|
||||
}
|
||||
|
||||
List<GroupMemberDto> memberDtos = req.getMembers();
|
||||
if(appConfig.isAddGroupMemberBeforeCallback()){
|
||||
|
||||
ResponseVO responseVO = callbackService.beforeCallback(req.getAppId(), Constants.CallbackCommand.GroupMemberAddBefore
|
||||
, JSONObject.toJSONString(req));
|
||||
if(!responseVO.isOk()){
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
try {
|
||||
memberDtos
|
||||
= JSONArray.parseArray(JSONObject.toJSONString(responseVO.getData()), GroupMemberDto.class);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
log.error("GroupMemberAddBefore 回调失败:{}",req.getAppId());
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupEntity group = groupResp.getData();
|
||||
|
||||
|
||||
/**
|
||||
* 私有群(private) 类似普通微信群,创建后仅支持已在群内的好友邀请加群,且无需被邀请方同意或群主审批
|
||||
* 公开群(Public) 类似 QQ 群,创建后群主可以指定群管理员,需要群主或管理员审批通过才能入群
|
||||
* 群类型 1私有群(类似微信) 2公开群(类似qq)
|
||||
*
|
||||
*/
|
||||
|
||||
if (!isAdmin && GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE);
|
||||
}
|
||||
|
||||
List<String> successId = new ArrayList<>();
|
||||
for (GroupMemberDto memberId :
|
||||
memberDtos) {
|
||||
ResponseVO responseVO = null;
|
||||
try {
|
||||
responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
responseVO = ResponseVO.errorResponse();
|
||||
}
|
||||
AddMemberResp addMemberResp = new AddMemberResp();
|
||||
addMemberResp.setMemberId(memberId.getMemberId());
|
||||
if (responseVO.isOk()) {
|
||||
successId.add(memberId.getMemberId());
|
||||
addMemberResp.setResult(0);
|
||||
} else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) {
|
||||
addMemberResp.setResult(2);
|
||||
addMemberResp.setResultMessage(responseVO.getMsg());
|
||||
} else {
|
||||
addMemberResp.setResult(1);
|
||||
addMemberResp.setResultMessage(responseVO.getMsg());
|
||||
}
|
||||
resp.add(addMemberResp);
|
||||
}
|
||||
|
||||
AddGroupMemberPack addGroupMemberPack = new AddGroupMemberPack();
|
||||
addGroupMemberPack.setGroupId(req.getGroupId());
|
||||
addGroupMemberPack.setMembers(successId);
|
||||
groupMessageProducer.producer(req.getOperater(), GroupEventCommand.ADDED_MEMBER, addGroupMemberPack
|
||||
, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
|
||||
if(appConfig.isAddGroupMemberAfterCallback()){
|
||||
AddMemberAfterCallback dto = new AddMemberAfterCallback();
|
||||
dto.setGroupId(req.getGroupId());
|
||||
dto.setGroupType(group.getGroupType());
|
||||
dto.setMemberId(resp);
|
||||
dto.setOperater(req.getOperater());
|
||||
callbackService.callback(req.getAppId()
|
||||
,Constants.CallbackCommand.GroupMemberAddAfter,
|
||||
JSONObject.toJSONString(dto));
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO removeMember(RemoveGroupMemberReq req) {
|
||||
|
||||
List<AddMemberResp> resp = new ArrayList<>();
|
||||
boolean isAdmin = false;
|
||||
ResponseVO<ImGroupEntity> groupResp = groupService.getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!groupResp.isOk()) {
|
||||
return groupResp;
|
||||
}
|
||||
|
||||
ImGroupEntity group = groupResp.getData();
|
||||
|
||||
if (!isAdmin) {
|
||||
if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) {
|
||||
|
||||
//获取操作人的权限 是管理员or群主or群成员
|
||||
ResponseVO<GetRoleInGroupResp> role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
if (!role.isOk()) {
|
||||
return role;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = role.getData();
|
||||
Integer roleInfo = data.getRole();
|
||||
|
||||
boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode();
|
||||
boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode();
|
||||
|
||||
if (!isOwner && !isManager) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
//私有群必须是群主才能踢人
|
||||
if (!isOwner && GroupTypeEnum.PRIVATE.getCode() == group.getGroupType()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
|
||||
//公开群管理员和群主可踢人,但管理员只能踢普通群成员
|
||||
if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) {
|
||||
// throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
//获取被踢人的权限
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId());
|
||||
if (!roleInGroupOne.isOk()) {
|
||||
return roleInGroupOne;
|
||||
}
|
||||
GetRoleInGroupResp memberRole = roleInGroupOne.getData();
|
||||
if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_OWNER_IS_NOT_REMOVE);
|
||||
}
|
||||
//是管理员并且被踢人不是群成员,无法操作
|
||||
if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ResponseVO responseVO = groupMemberService.removeGroupMember(req.getGroupId(), req.getAppId(), req.getMemberId());
|
||||
if(responseVO.isOk()){
|
||||
|
||||
RemoveGroupMemberPack removeGroupMemberPack = new RemoveGroupMemberPack();
|
||||
removeGroupMemberPack.setGroupId(req.getGroupId());
|
||||
removeGroupMemberPack.setMember(req.getMemberId());
|
||||
groupMessageProducer.producer(req.getMemberId(), GroupEventCommand.DELETED_MEMBER, removeGroupMemberPack
|
||||
, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
if(appConfig.isDeleteGroupMemberAfterCallback()){
|
||||
callbackService.callback(req.getAppId(),
|
||||
Constants.CallbackCommand.GroupMemberDeleteAfter,
|
||||
JSONObject.toJSONString(req));
|
||||
}
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO<List<GroupMemberDto>> getGroupMember(String groupId, Integer appId) {
|
||||
List<GroupMemberDto> groupMember = imGroupMemberMapper.getGroupMember(appId, groupId);
|
||||
return ResponseVO.successResponse(groupMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroupMemberId(String groupId, Integer appId) {
|
||||
return imGroupMemberMapper.getGroupMemberId(appId, groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupMemberDto> getGroupManager(String groupId, Integer appId) {
|
||||
return imGroupMemberMapper.getGroupManager(groupId, appId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO updateGroupMember(UpdateGroupMemberReq req) {
|
||||
|
||||
boolean isadmin = false;
|
||||
|
||||
ResponseVO<ImGroupEntity> group = groupService.getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!group.isOk()) {
|
||||
return group;
|
||||
}
|
||||
|
||||
ImGroupEntity groupData = group.getData();
|
||||
if (groupData.getStatus() == GroupStatusEnum.DESTROY.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
|
||||
}
|
||||
|
||||
//是否是自己修改自己的资料
|
||||
boolean isMeOperate = req.getOperater().equals(req.getMemberId());
|
||||
|
||||
if (!isadmin) {
|
||||
//昵称只能自己修改 权限只能群主或管理员修改
|
||||
if (StringUtils.isBlank(req.getAlias()) && !isMeOperate) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_ONESELF);
|
||||
}
|
||||
//私有群不能设置管理员
|
||||
if (groupData.getGroupType() == GroupTypeEnum.PRIVATE.getCode() &&
|
||||
req.getRole() != null && (req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() ||
|
||||
req.getRole() == GroupMemberRoleEnum.OWNER.getCode())) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
//如果要修改权限相关的则走下面的逻辑
|
||||
if(req.getRole() != null){
|
||||
//获取被操作人的是否在群内
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId());
|
||||
if(!roleInGroupOne.isOk()){
|
||||
return roleInGroupOne;
|
||||
}
|
||||
|
||||
//获取操作人权限
|
||||
ResponseVO<GetRoleInGroupResp> operateRoleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
if(!operateRoleInGroupOne.isOk()){
|
||||
return operateRoleInGroupOne;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = operateRoleInGroupOne.getData();
|
||||
Integer roleInfo = data.getRole();
|
||||
boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode();
|
||||
boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode();
|
||||
|
||||
//不是管理员不能修改权限
|
||||
if(req.getRole() != null && !isOwner && !isManager){
|
||||
return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
//管理员只有群主能够设置
|
||||
if(req.getRole() != null && req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() && !isOwner){
|
||||
return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupMemberEntity update = new ImGroupMemberEntity();
|
||||
|
||||
if (StringUtils.isNotBlank(req.getAlias())) {
|
||||
update.setAlias(req.getAlias());
|
||||
}
|
||||
|
||||
//不能直接修改为群主
|
||||
if(req.getRole() != null && req.getRole() != GroupMemberRoleEnum.OWNER.getCode()){
|
||||
update.setRole(req.getRole());
|
||||
}
|
||||
|
||||
UpdateWrapper<ImGroupMemberEntity> objectUpdateWrapper = new UpdateWrapper<>();
|
||||
objectUpdateWrapper.eq("app_id", req.getAppId());
|
||||
objectUpdateWrapper.eq("member_id", req.getMemberId());
|
||||
objectUpdateWrapper.eq("group_id", req.getGroupId());
|
||||
imGroupMemberMapper.update(update, objectUpdateWrapper);
|
||||
|
||||
UpdateGroupMemberPack pack = new UpdateGroupMemberPack();
|
||||
BeanUtils.copyProperties(req, pack);
|
||||
groupMessageProducer.producer(req.getOperater(), GroupEventCommand.UPDATED_MEMBER, pack, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO transferGroupMember(String owner, String groupId, Integer appId) {
|
||||
|
||||
//更新旧群主
|
||||
ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity();
|
||||
imGroupMemberEntity.setRole(GroupMemberRoleEnum.ORDINARY.getCode());
|
||||
UpdateWrapper<ImGroupMemberEntity> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("app_id", appId);
|
||||
updateWrapper.eq("group_id", groupId);
|
||||
updateWrapper.eq("role", GroupMemberRoleEnum.OWNER.getCode());
|
||||
imGroupMemberMapper.update(imGroupMemberEntity, updateWrapper);
|
||||
|
||||
//更新新群主
|
||||
ImGroupMemberEntity newOwner = new ImGroupMemberEntity();
|
||||
newOwner.setRole(GroupMemberRoleEnum.OWNER.getCode());
|
||||
UpdateWrapper<ImGroupMemberEntity> ownerWrapper = new UpdateWrapper<>();
|
||||
ownerWrapper.eq("app_id", appId);
|
||||
ownerWrapper.eq("group_id", groupId);
|
||||
ownerWrapper.eq("member_id", owner);
|
||||
imGroupMemberMapper.update(newOwner, ownerWrapper);
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO speak(SpeaMemberReq req) {
|
||||
|
||||
ResponseVO<ImGroupEntity> groupResp = groupService.getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!groupResp.isOk()) {
|
||||
return groupResp;
|
||||
}
|
||||
|
||||
boolean isadmin = false;
|
||||
boolean isOwner = false;
|
||||
boolean isManager = false;
|
||||
GetRoleInGroupResp memberRole = null;
|
||||
|
||||
if (!isadmin) {
|
||||
|
||||
//获取操作人的权限 是管理员or群主or群成员
|
||||
ResponseVO<GetRoleInGroupResp> role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
if (!role.isOk()) {
|
||||
return role;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = role.getData();
|
||||
Integer roleInfo = data.getRole();
|
||||
|
||||
isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode();
|
||||
isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode();
|
||||
|
||||
if (!isOwner && !isManager) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
//获取被操作的权限
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId());
|
||||
if (!roleInGroupOne.isOk()) {
|
||||
return roleInGroupOne;
|
||||
}
|
||||
memberRole = roleInGroupOne.getData();
|
||||
//被操作人是群主只能app管理员操作
|
||||
if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE);
|
||||
}
|
||||
|
||||
//是管理员并且被操作人不是群成员,无法操作
|
||||
if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity();
|
||||
if(memberRole == null){
|
||||
//获取被操作的权限
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId());
|
||||
if (!roleInGroupOne.isOk()) {
|
||||
return roleInGroupOne;
|
||||
}
|
||||
memberRole = roleInGroupOne.getData();
|
||||
}
|
||||
|
||||
imGroupMemberEntity.setGroupMemberId(memberRole.getGroupMemberId());
|
||||
if(req.getSpeakDate() > 0){
|
||||
imGroupMemberEntity.setSpeakDate(System.currentTimeMillis() + req.getSpeakDate());
|
||||
}else{
|
||||
imGroupMemberEntity.setSpeakDate(req.getSpeakDate());
|
||||
}
|
||||
|
||||
int i = imGroupMemberMapper.updateById(imGroupMemberEntity);
|
||||
if(i == 1){
|
||||
GroupMemberSpeakPack pack = new GroupMemberSpeakPack();
|
||||
BeanUtils.copyProperties(req,pack);
|
||||
groupMessageProducer.producer(req.getOperater(),GroupEventCommand.SPEAK_GOUP_MEMBER,pack,
|
||||
new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
|
||||
}
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO<Collection<String>> syncMemberJoinedGroup(String operater, Integer appId) {
|
||||
return ResponseVO.successResponse(imGroupMemberMapper.syncJoinedGroupId(appId,operater,GroupMemberRoleEnum.LEAVE.getCode()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
package com.lld.im.service.group.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.lld.im.codec.pack.group.CreateGroupPack;
|
||||
import com.lld.im.codec.pack.group.DestroyGroupPack;
|
||||
import com.lld.im.codec.pack.group.UpdateGroupInfoPack;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.GroupErrorCode;
|
||||
import com.lld.im.common.enums.GroupMemberRoleEnum;
|
||||
import com.lld.im.common.enums.GroupStatusEnum;
|
||||
import com.lld.im.common.enums.GroupTypeEnum;
|
||||
import com.lld.im.common.enums.command.GroupEventCommand;
|
||||
import com.lld.im.common.exception.ApplicationException;
|
||||
import com.lld.im.common.model.ClientInfo;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.common.model.SyncResp;
|
||||
import com.lld.im.service.conversation.dao.ImConversationSetEntity;
|
||||
import com.lld.im.service.group.dao.ImGroupEntity;
|
||||
import com.lld.im.service.group.dao.mapper.ImGroupMapper;
|
||||
import com.lld.im.service.group.model.callback.DestroyGroupCallbackDto;
|
||||
import com.lld.im.service.group.model.req.*;
|
||||
import com.lld.im.service.group.model.resp.GetGroupResp;
|
||||
import com.lld.im.service.group.model.resp.GetJoinedGroupResp;
|
||||
import com.lld.im.service.group.model.resp.GetRoleInGroupResp;
|
||||
import com.lld.im.service.group.service.ImGroupMemberService;
|
||||
import com.lld.im.service.group.service.ImGroupService;
|
||||
import com.lld.im.service.seq.RedisSeq;
|
||||
import com.lld.im.service.utils.CallbackService;
|
||||
import com.lld.im.service.utils.GroupMessageProducer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class ImGroupServiceImpl implements ImGroupService {
|
||||
|
||||
@Autowired
|
||||
ImGroupMapper imGroupDataMapper;
|
||||
|
||||
@Autowired
|
||||
ImGroupMemberService groupMemberService;
|
||||
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Autowired
|
||||
CallbackService callbackService;
|
||||
|
||||
@Autowired
|
||||
GroupMessageProducer groupMessageProducer;
|
||||
|
||||
@Autowired
|
||||
RedisSeq redisSeq;
|
||||
|
||||
@Override
|
||||
public ResponseVO importGroup(ImportGroupReq req) {
|
||||
|
||||
//1.判断群id是否存在
|
||||
QueryWrapper<ImGroupEntity> query = new QueryWrapper<>();
|
||||
|
||||
if (StringUtils.isEmpty(req.getGroupId())) {
|
||||
req.setGroupId(UUID.randomUUID().toString().replace("-", ""));
|
||||
} else {
|
||||
query.eq("group_id", req.getGroupId());
|
||||
query.eq("app_id", req.getAppId());
|
||||
Integer integer = imGroupDataMapper.selectCount(query);
|
||||
if (integer > 0) {
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupEntity imGroupEntity = new ImGroupEntity();
|
||||
|
||||
if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) {
|
||||
throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER);
|
||||
}
|
||||
|
||||
if (req.getCreateTime() == null) {
|
||||
imGroupEntity.setCreateTime(System.currentTimeMillis());
|
||||
}
|
||||
imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode());
|
||||
BeanUtils.copyProperties(req, imGroupEntity);
|
||||
int insert = imGroupDataMapper.insert(imGroupEntity);
|
||||
|
||||
if (insert != 1) {
|
||||
throw new ApplicationException(GroupErrorCode.IMPORT_GROUP_ERROR);
|
||||
}
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO createGroup(CreateGroupReq req) {
|
||||
|
||||
boolean isAdmin = false;
|
||||
|
||||
if (!isAdmin) {
|
||||
req.setOwnerId(req.getOperater());
|
||||
}
|
||||
|
||||
//1.判断群id是否存在
|
||||
QueryWrapper<ImGroupEntity> query = new QueryWrapper<>();
|
||||
|
||||
if (StringUtils.isEmpty(req.getGroupId())) {
|
||||
req.setGroupId(UUID.randomUUID().toString().replace("-", ""));
|
||||
} else {
|
||||
query.eq("group_id", req.getGroupId());
|
||||
query.eq("app_id", req.getAppId());
|
||||
Integer integer = imGroupDataMapper.selectCount(query);
|
||||
if (integer > 0) {
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) {
|
||||
throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER);
|
||||
}
|
||||
|
||||
ImGroupEntity imGroupEntity = new ImGroupEntity();
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Group);
|
||||
imGroupEntity.setSequence(seq);
|
||||
imGroupEntity.setCreateTime(System.currentTimeMillis());
|
||||
imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode());
|
||||
BeanUtils.copyProperties(req, imGroupEntity);
|
||||
int insert = imGroupDataMapper.insert(imGroupEntity);
|
||||
|
||||
GroupMemberDto groupMemberDto = new GroupMemberDto();
|
||||
groupMemberDto.setMemberId(req.getOwnerId());
|
||||
groupMemberDto.setRole(GroupMemberRoleEnum.OWNER.getCode());
|
||||
groupMemberDto.setJoinTime(System.currentTimeMillis());
|
||||
groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), groupMemberDto);
|
||||
|
||||
//插入群成员
|
||||
for (GroupMemberDto dto : req.getMember()) {
|
||||
groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), dto);
|
||||
}
|
||||
|
||||
if(appConfig.isCreateGroupAfterCallback()){
|
||||
callbackService.callback(req.getAppId(), Constants.CallbackCommand.CreateGroupAfter,
|
||||
JSONObject.toJSONString(imGroupEntity));
|
||||
}
|
||||
|
||||
CreateGroupPack createGroupPack = new CreateGroupPack();
|
||||
BeanUtils.copyProperties(imGroupEntity, createGroupPack);
|
||||
groupMessageProducer.producer(req.getOperater(), GroupEventCommand.CREATED_GROUP, createGroupPack
|
||||
, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [req]
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description 修改群基础信息,如果是后台管理员调用,则不检查权限,如果不是则检查权限,如果是私有群(微信群)任何人都可以修改资料,公开群只有管理员可以修改
|
||||
* 如果是群主或者管理员可以修改其他信息。
|
||||
* @author chackylee
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO updateBaseGroupInfo(UpdateGroupReq req) {
|
||||
|
||||
//1.判断群id是否存在
|
||||
QueryWrapper<ImGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("group_id", req.getGroupId());
|
||||
query.eq("app_id", req.getAppId());
|
||||
ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query);
|
||||
if (imGroupEntity == null) {
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST);
|
||||
}
|
||||
|
||||
if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
|
||||
}
|
||||
|
||||
boolean isAdmin = false;
|
||||
|
||||
if (!isAdmin) {
|
||||
//不是后台调用需要检查权限
|
||||
ResponseVO<GetRoleInGroupResp> role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
|
||||
if (!role.isOk()) {
|
||||
return role;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = role.getData();
|
||||
Integer roleInfo = data.getRole();
|
||||
|
||||
boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode();
|
||||
|
||||
//公开群只能群主修改资料
|
||||
if (!isManager && GroupTypeEnum.PUBLIC.getCode() == imGroupEntity.getGroupType()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ImGroupEntity update = new ImGroupEntity();
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Group);
|
||||
BeanUtils.copyProperties(req, update);
|
||||
update.setUpdateTime(System.currentTimeMillis());
|
||||
update.setSequence(seq);
|
||||
int row = imGroupDataMapper.update(update, query);
|
||||
if (row != 1) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
if(appConfig.isModifyGroupAfterCallback()){
|
||||
callbackService.callback(req.getAppId(),Constants.CallbackCommand.UpdateGroupAfter,
|
||||
JSONObject.toJSONString(imGroupDataMapper.selectOne(query)));
|
||||
}
|
||||
|
||||
UpdateGroupInfoPack pack = new UpdateGroupInfoPack();
|
||||
BeanUtils.copyProperties(req, pack);
|
||||
groupMessageProducer.producer(req.getOperater(), GroupEventCommand.UPDATED_GROUP,
|
||||
pack, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [req]
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description 获取用户加入的群组
|
||||
* @author chackylee
|
||||
*/
|
||||
@Override
|
||||
public ResponseVO getJoinedGroup(GetJoinedGroupReq req) {
|
||||
|
||||
ResponseVO<Collection<String>> memberJoinedGroup = groupMemberService.getMemberJoinedGroup(req);
|
||||
if (memberJoinedGroup.isOk()) {
|
||||
|
||||
GetJoinedGroupResp resp = new GetJoinedGroupResp();
|
||||
|
||||
if (CollectionUtils.isEmpty(memberJoinedGroup.getData())) {
|
||||
resp.setTotalCount(0);
|
||||
resp.setGroupList(new ArrayList<>());
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
QueryWrapper<ImGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id", req.getAppId());
|
||||
query.in("group_id", memberJoinedGroup.getData());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(req.getGroupType())) {
|
||||
query.in("group_type", req.getGroupType());
|
||||
}
|
||||
|
||||
List<ImGroupEntity> groupList = imGroupDataMapper.selectList(query);
|
||||
resp.setGroupList(groupList);
|
||||
if (req.getLimit() == null) {
|
||||
resp.setTotalCount(groupList.size());
|
||||
} else {
|
||||
resp.setTotalCount(imGroupDataMapper.selectCount(query));
|
||||
}
|
||||
return ResponseVO.successResponse(resp);
|
||||
} else {
|
||||
return memberJoinedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param [req]
|
||||
* @return com.lld.im.common.ResponseVO
|
||||
* @description 解散群组,只支持后台管理员和群主解散
|
||||
* @author chackylee
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO destroyGroup(DestroyGroupReq req) {
|
||||
|
||||
boolean isAdmin = false;
|
||||
|
||||
QueryWrapper<ImGroupEntity> objectQueryWrapper = new QueryWrapper<>();
|
||||
objectQueryWrapper.eq("group_id", req.getGroupId());
|
||||
objectQueryWrapper.eq("app_id", req.getAppId());
|
||||
ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper);
|
||||
if (imGroupEntity == null) {
|
||||
throw new ApplicationException(GroupErrorCode.PRIVATE_GROUP_CAN_NOT_DESTORY);
|
||||
}
|
||||
|
||||
if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
|
||||
}
|
||||
|
||||
if (!isAdmin) {
|
||||
if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode()) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
|
||||
if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode() &&
|
||||
!imGroupEntity.getOwnerId().equals(req.getOperater())) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupEntity update = new ImGroupEntity();
|
||||
long seq = redisSeq.doGetSeq(req.getAppId() + ":" + Constants.SeqConstants.Group);
|
||||
|
||||
update.setStatus(GroupStatusEnum.DESTROY.getCode());
|
||||
update.setSequence(seq);
|
||||
int update1 = imGroupDataMapper.update(update, objectQueryWrapper);
|
||||
if (update1 != 1) {
|
||||
throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR);
|
||||
}
|
||||
|
||||
if(appConfig.isModifyGroupAfterCallback()){
|
||||
DestroyGroupCallbackDto dto = new DestroyGroupCallbackDto();
|
||||
dto.setGroupId(req.getGroupId());
|
||||
callbackService.callback(req.getAppId()
|
||||
,Constants.CallbackCommand.DestoryGroupAfter,
|
||||
JSONObject.toJSONString(dto));
|
||||
}
|
||||
|
||||
DestroyGroupPack pack = new DestroyGroupPack();
|
||||
pack.setSequence(seq);
|
||||
pack.setGroupId(req.getGroupId());
|
||||
groupMessageProducer.producer(req.getOperater(),
|
||||
GroupEventCommand.DESTROY_GROUP, pack, new ClientInfo(req.getAppId(), req.getClientType(), req.getImei()));
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseVO transferGroup(TransferGroupReq req) {
|
||||
|
||||
ResponseVO<GetRoleInGroupResp> roleInGroupOne = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
if (!roleInGroupOne.isOk()) {
|
||||
return roleInGroupOne;
|
||||
}
|
||||
|
||||
if (roleInGroupOne.getData().getRole() != GroupMemberRoleEnum.OWNER.getCode()) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
|
||||
}
|
||||
|
||||
ResponseVO<GetRoleInGroupResp> newOwnerRole = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOwnerId(), req.getAppId());
|
||||
if (!newOwnerRole.isOk()) {
|
||||
return newOwnerRole;
|
||||
}
|
||||
|
||||
QueryWrapper<ImGroupEntity> objectQueryWrapper = new QueryWrapper<>();
|
||||
objectQueryWrapper.eq("group_id", req.getGroupId());
|
||||
objectQueryWrapper.eq("app_id", req.getAppId());
|
||||
ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper);
|
||||
if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
|
||||
}
|
||||
|
||||
ImGroupEntity updateGroup = new ImGroupEntity();
|
||||
updateGroup.setOwnerId(req.getOwnerId());
|
||||
UpdateWrapper<ImGroupEntity> updateGroupWrapper = new UpdateWrapper<>();
|
||||
updateGroupWrapper.eq("app_id", req.getAppId());
|
||||
updateGroupWrapper.eq("group_id", req.getGroupId());
|
||||
imGroupDataMapper.update(updateGroup, updateGroupWrapper);
|
||||
groupMemberService.transferGroupMember(req.getOwnerId(), req.getGroupId(), req.getAppId());
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO getGroup(String groupId, Integer appId) {
|
||||
|
||||
QueryWrapper<ImGroupEntity> query = new QueryWrapper<>();
|
||||
query.eq("app_id", appId);
|
||||
query.eq("group_id", groupId);
|
||||
ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query);
|
||||
|
||||
if (imGroupEntity == null) {
|
||||
return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_NOT_EXIST);
|
||||
}
|
||||
return ResponseVO.successResponse(imGroupEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO getGroup(GetGroupReq req) {
|
||||
|
||||
ResponseVO group = this.getGroup(req.getGroupId(), req.getAppId());
|
||||
|
||||
if(!group.isOk()){
|
||||
return group;
|
||||
}
|
||||
|
||||
GetGroupResp getGroupResp = new GetGroupResp();
|
||||
BeanUtils.copyProperties(group.getData(), getGroupResp);
|
||||
try {
|
||||
ResponseVO<List<GroupMemberDto>> groupMember = groupMemberService.getGroupMember(req.getGroupId(), req.getAppId());
|
||||
if (groupMember.isOk()) {
|
||||
getGroupResp.setMemberList(groupMember.getData());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ResponseVO.successResponse(getGroupResp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO muteGroup(MuteGroupReq req) {
|
||||
|
||||
ResponseVO<ImGroupEntity> groupResp = getGroup(req.getGroupId(), req.getAppId());
|
||||
if (!groupResp.isOk()) {
|
||||
return groupResp;
|
||||
}
|
||||
|
||||
if(groupResp.getData().getStatus() == GroupStatusEnum.DESTROY.getCode()){
|
||||
throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
|
||||
}
|
||||
|
||||
boolean isadmin = false;
|
||||
|
||||
if (!isadmin) {
|
||||
//不是后台调用需要检查权限
|
||||
ResponseVO<GetRoleInGroupResp> role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
|
||||
|
||||
if (!role.isOk()) {
|
||||
return role;
|
||||
}
|
||||
|
||||
GetRoleInGroupResp data = role.getData();
|
||||
Integer roleInfo = data.getRole();
|
||||
|
||||
boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode();
|
||||
|
||||
//公开群只能群主修改资料
|
||||
if (!isManager) {
|
||||
throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
|
||||
}
|
||||
}
|
||||
|
||||
ImGroupEntity update = new ImGroupEntity();
|
||||
update.setMute(req.getMute());
|
||||
|
||||
UpdateWrapper<ImGroupEntity> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("group_id",req.getGroupId());
|
||||
wrapper.eq("app_id",req.getAppId());
|
||||
imGroupDataMapper.update(update,wrapper);
|
||||
|
||||
return ResponseVO.successResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseVO syncJoinedGroupList(SyncReq req) {
|
||||
if(req.getMaxLimit() > 100){
|
||||
req.setMaxLimit(100);
|
||||
}
|
||||
|
||||
SyncResp<ImGroupEntity> resp = new SyncResp<>();
|
||||
|
||||
ResponseVO<Collection<String>> memberJoinedGroup = groupMemberService.syncMemberJoinedGroup(req.getOperater(), req.getAppId());
|
||||
if(memberJoinedGroup.isOk()){
|
||||
|
||||
Collection<String> data = memberJoinedGroup.getData();
|
||||
QueryWrapper<ImGroupEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("app_id",req.getAppId());
|
||||
queryWrapper.in("group_id",data);
|
||||
queryWrapper.gt("sequence",req.getLastSequence());
|
||||
queryWrapper.last(" limit " + req.getMaxLimit());
|
||||
queryWrapper.orderByAsc("sequence");
|
||||
|
||||
List<ImGroupEntity> list = imGroupDataMapper.selectList(queryWrapper);
|
||||
|
||||
if(!CollectionUtils.isEmpty(list)){
|
||||
ImGroupEntity maxSeqEntity
|
||||
= list.get(list.size() - 1);
|
||||
resp.setDataList(list);
|
||||
//设置最大seq
|
||||
Long maxSeq =
|
||||
imGroupDataMapper.getGroupMaxSeq(data, req.getAppId());
|
||||
resp.setMaxSequence(maxSeq);
|
||||
//设置是否拉取完毕
|
||||
resp.setCompleted(maxSeqEntity.getSequence() >= maxSeq);
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
}
|
||||
resp.setCompleted(true);
|
||||
return ResponseVO.successResponse(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getUserGroupMaxSeq(String userId, Integer appId) {
|
||||
|
||||
ResponseVO<Collection<String>> memberJoinedGroup = groupMemberService.syncMemberJoinedGroup(userId, appId);
|
||||
if(!memberJoinedGroup.isOk()){
|
||||
throw new ApplicationException(500,"");
|
||||
}
|
||||
Long maxSeq =
|
||||
imGroupDataMapper.getGroupMaxSeq(memberJoinedGroup.getData(),
|
||||
appId);
|
||||
return maxSeq;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.lld.im.service.interceptor;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.lld.im.common.BaseErrorCode;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.enums.GateWayErrorCode;
|
||||
import com.lld.im.common.exception.ApplicationExceptionEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Component
|
||||
public class GateWayInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
IdentityCheck identityCheck;
|
||||
|
||||
|
||||
//appService -》im接口 -》 userSign
|
||||
//appService(gen userSig)
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
// if (1 == 1){
|
||||
// return true;
|
||||
// }
|
||||
|
||||
//获取appId 操作人 userSign
|
||||
String appIdStr = request.getParameter("appId");
|
||||
if(StringUtils.isBlank(appIdStr)){
|
||||
resp(ResponseVO.errorResponse(GateWayErrorCode
|
||||
.APPID_NOT_EXIST),response);
|
||||
return false;
|
||||
}
|
||||
|
||||
String identifier = request.getParameter("identifier");
|
||||
if(StringUtils.isBlank(identifier)){
|
||||
resp(ResponseVO.errorResponse(GateWayErrorCode
|
||||
.OPERATER_NOT_EXIST),response);
|
||||
return false;
|
||||
}
|
||||
|
||||
String userSign = request.getParameter("userSign");
|
||||
if(StringUtils.isBlank(userSign)){
|
||||
resp(ResponseVO.errorResponse(GateWayErrorCode
|
||||
.USERSIGN_NOT_EXIST),response);
|
||||
return false;
|
||||
}
|
||||
|
||||
//签名和操作人和appid是否匹配
|
||||
ApplicationExceptionEnum applicationExceptionEnum = identityCheck.checkUserSig(identifier, appIdStr, userSign);
|
||||
if(applicationExceptionEnum != BaseErrorCode.SUCCESS){
|
||||
resp(ResponseVO.errorResponse(applicationExceptionEnum),response);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void resp(ResponseVO respVo ,HttpServletResponse response){
|
||||
|
||||
PrintWriter writer = null;
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("text/html; charset=utf-8");
|
||||
try {
|
||||
String resp = JSONObject.toJSONString(respVo);
|
||||
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("Content-type", "application/json;charset=UTF-8");
|
||||
response.setHeader("Access-Control-Allow-Origin","*");
|
||||
response.setHeader("Access-Control-Allow-Credentials","true");
|
||||
response.setHeader("Access-Control-Allow-Methods","*");
|
||||
response.setHeader("Access-Control-Allow-Headers","*");
|
||||
response.setHeader("Access-Control-Max-Age","3600");
|
||||
|
||||
writer = response.getWriter();
|
||||
writer.write(resp);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(writer != null){
|
||||
writer.checkError();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.lld.im.service.interceptor;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.lld.im.common.BaseErrorCode;
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.config.AppConfig;
|
||||
import com.lld.im.common.constant.Constants;
|
||||
import com.lld.im.common.enums.GateWayErrorCode;
|
||||
import com.lld.im.common.enums.ImUserTypeEnum;
|
||||
import com.lld.im.common.exception.ApplicationExceptionEnum;
|
||||
import com.lld.im.common.utils.SigAPI;
|
||||
import com.lld.im.service.user.dao.ImUserDataEntity;
|
||||
import com.lld.im.service.user.service.ImUserService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import sun.rmi.runtime.Log;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Component
|
||||
public class IdentityCheck {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(IdentityCheck.class);
|
||||
|
||||
@Autowired
|
||||
ImUserService imUserService;
|
||||
|
||||
//10000 123456 10001 123456789
|
||||
@Autowired
|
||||
AppConfig appConfig;
|
||||
|
||||
@Autowired
|
||||
StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
public ApplicationExceptionEnum checkUserSig(String identifier,
|
||||
String appId,String userSig){
|
||||
|
||||
String cacheUserSig = stringRedisTemplate.opsForValue()
|
||||
.get(appId + ":" + Constants.RedisConstants.userSign + ":"
|
||||
+ identifier + userSig);
|
||||
if(!StringUtils.isBlank(cacheUserSig) && Long.valueOf(cacheUserSig)
|
||||
> System.currentTimeMillis() / 1000){
|
||||
this.setIsAdmin(identifier,Integer.valueOf(appId));
|
||||
return BaseErrorCode.SUCCESS;
|
||||
}
|
||||
|
||||
//获取秘钥
|
||||
String privateKey = appConfig.getPrivateKey();
|
||||
|
||||
//根据appid + 秘钥创建sigApi
|
||||
SigAPI sigAPI = new SigAPI(Long.valueOf(appId), privateKey);
|
||||
|
||||
//调用sigApi对userSig解密
|
||||
JSONObject jsonObject = sigAPI.decodeUserSig(userSig);
|
||||
|
||||
//取出解密后的appid 和 操作人 和 过期时间做匹配,不通过则提示错误
|
||||
Long expireTime = 0L;
|
||||
Long expireSec = 0L;
|
||||
Long time = 0L;
|
||||
String decoerAppId = "";
|
||||
String decoderidentifier = "";
|
||||
|
||||
try {
|
||||
decoerAppId = jsonObject.getString("TLS.appId");
|
||||
decoderidentifier = jsonObject.getString("TLS.identifier");
|
||||
String expireStr = jsonObject.get("TLS.expire").toString();
|
||||
String expireTimeStr = jsonObject.get("TLS.expireTime").toString();
|
||||
time = Long.valueOf(expireTimeStr);
|
||||
expireSec = Long.valueOf(expireStr);
|
||||
expireTime = Long.valueOf(expireTimeStr) + expireSec;
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
logger.error("checkUserSig-error:{}",e.getMessage());
|
||||
}
|
||||
|
||||
if(!decoderidentifier.equals(identifier)){
|
||||
return GateWayErrorCode.USERSIGN_OPERATE_NOT_MATE;
|
||||
}
|
||||
|
||||
if(!decoerAppId.equals(appId)){
|
||||
return GateWayErrorCode.USERSIGN_IS_ERROR;
|
||||
}
|
||||
|
||||
if(expireSec == 0L){
|
||||
return GateWayErrorCode.USERSIGN_IS_EXPIRED;
|
||||
}
|
||||
|
||||
if(expireTime < System.currentTimeMillis() / 1000){
|
||||
return GateWayErrorCode.USERSIGN_IS_EXPIRED;
|
||||
}
|
||||
|
||||
//appid + "xxx" + userId + sign
|
||||
String genSig = sigAPI.genUserSig(identifier, expireSec,time,null);
|
||||
if (genSig.toLowerCase().equals(userSig.toLowerCase()))
|
||||
{
|
||||
String key = appId + ":" + Constants.RedisConstants.userSign + ":"
|
||||
+identifier + userSig;
|
||||
|
||||
Long etime = expireTime - System.currentTimeMillis() / 1000;
|
||||
stringRedisTemplate.opsForValue().set(
|
||||
key,expireTime.toString(),etime, TimeUnit.SECONDS
|
||||
);
|
||||
this.setIsAdmin(identifier,Integer.valueOf(appId));
|
||||
return BaseErrorCode.SUCCESS;
|
||||
}
|
||||
|
||||
return GateWayErrorCode.USERSIGN_IS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据appid,identifier判断是否App管理员,并设置到RequestHolder
|
||||
* @param identifier
|
||||
* @param appId
|
||||
* @return
|
||||
*/
|
||||
public void setIsAdmin(String identifier, Integer appId) {
|
||||
//去DB或Redis中查找, 后面写
|
||||
ResponseVO<ImUserDataEntity> singleUserInfo = imUserService.getSingleUserInfo(identifier, appId);
|
||||
if(singleUserInfo.isOk()){
|
||||
RequestHolder.set(singleUserInfo.getData().getUserType() == ImUserTypeEnum.APP_ADMIN.getCode());
|
||||
}else{
|
||||
RequestHolder.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lld.im.service.interceptor;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
public class RequestHolder {
|
||||
|
||||
private final static ThreadLocal<Boolean> requestHolder = new ThreadLocal<>();
|
||||
|
||||
public static void set(Boolean isadmin) {
|
||||
requestHolder.set(isadmin);
|
||||
}
|
||||
|
||||
public static Boolean get() {
|
||||
return requestHolder.get();
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
requestHolder.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.lld.im.service.message.controller;
|
||||
|
||||
import com.lld.im.common.ResponseVO;
|
||||
import com.lld.im.common.model.SyncReq;
|
||||
import com.lld.im.common.model.message.CheckSendMessageReq;
|
||||
import com.lld.im.service.message.model.req.SendMessageReq;
|
||||
import com.lld.im.service.message.service.MessageSyncService;
|
||||
import com.lld.im.service.message.service.P2PMessageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("v1/message")
|
||||
public class MessageController {
|
||||
|
||||
@Autowired
|
||||
P2PMessageService p2PMessageService;
|
||||
|
||||
@Autowired
|
||||
MessageSyncService messageSyncService;
|
||||
|
||||
@RequestMapping("/send")
|
||||
public ResponseVO send(@RequestBody @Validated SendMessageReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return ResponseVO.successResponse(p2PMessageService.send(req));
|
||||
}
|
||||
|
||||
@RequestMapping("/checkSend")
|
||||
public ResponseVO checkSend(@RequestBody @Validated CheckSendMessageReq req) {
|
||||
return p2PMessageService.imServerPermissionCheck(req.getFromId(),req.getToId()
|
||||
,req.getAppId());
|
||||
}
|
||||
|
||||
@RequestMapping("/syncOfflineMessage")
|
||||
public ResponseVO syncOfflineMessage(@RequestBody
|
||||
@Validated SyncReq req, Integer appId) {
|
||||
req.setAppId(appId);
|
||||
return messageSyncService.syncOfflineMessage(req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.lld.im.service.message.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
@TableName("im_message_body")
|
||||
public class ImMessageBodyEntity {
|
||||
|
||||
private Integer appId;
|
||||
|
||||
/** messageBodyId*/
|
||||
private Long messageKey;
|
||||
|
||||
/** messageBody*/
|
||||
private String messageBody;
|
||||
|
||||
private String securityKey;
|
||||
|
||||
private Long messageTime;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
private String extra;
|
||||
|
||||
private Integer delFlag;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.lld.im.service.message.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
@TableName("im_message_history")
|
||||
public class ImMessageHistoryEntity {
|
||||
|
||||
private Integer appId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
|
||||
private String ownerId;
|
||||
|
||||
/** messageBodyId*/
|
||||
private Long messageKey;
|
||||
/** 序列号*/
|
||||
private Long sequence;
|
||||
|
||||
private String messageRandom;
|
||||
|
||||
private Long messageTime;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lld.im.service.message.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.message.dao.ImMessageBodyEntity;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ImMessageBodyMapper extends BaseMapper<ImMessageBodyEntity> {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lld.im.service.message.dao.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.lld.im.service.message.dao.ImMessageHistoryEntity;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Repository
|
||||
public interface ImMessageHistoryMapper extends BaseMapper<ImMessageHistoryEntity> {
|
||||
|
||||
/**
|
||||
* 批量插入(mysql)
|
||||
* @param entityList
|
||||
* @return
|
||||
*/
|
||||
Integer insertBatchSomeColumn(Collection<ImMessageHistoryEntity> entityList);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lld.im.service.message.model.req;
|
||||
|
||||
import com.lld.im.common.model.RequestBase;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: Chackylee
|
||||
* @description:
|
||||
**/
|
||||
@Data
|
||||
public class SendMessageReq extends RequestBase {
|
||||
|
||||
//客户端传的messageId
|
||||
private String messageId;
|
||||
|
||||
private String fromId;
|
||||
|
||||
private String toId;
|
||||
|
||||
private int messageRandom;
|
||||
|
||||
private long messageTime;
|
||||
|
||||
private String messageBody;
|
||||
/**
|
||||
* 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加
|
||||
*/
|
||||
private int badgeMode;
|
||||
|
||||
private Long messageLifeTime;
|
||||
|
||||
private Integer appId;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user