Commit 8ad3c91c by Future

Merge branch 'feature-cluster' into paas-prod

parents 9b0dc6fb 4ee85807
......@@ -31,6 +31,11 @@
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>scheduled</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -22,6 +22,8 @@ import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.dispatch.extend.ArgumentBox;
import io.geekidea.springbootplus.config.properties.SwaggerProperties;
import io.geekidea.springbootplus.framework.common.exception.SpringBootPlusConfigException;
import io.swagger.annotations.Api;
......@@ -102,6 +104,8 @@ public class Swagger2Config {
HttpServletRequest.class,
HttpServletResponse.class,
HttpSession.class,
ActionRequest.class,
ArgumentBox.class,
ApiIgnore.class
};
@Autowired
......
package io.geekidea.springbootplus.test;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.DeviceTypeEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.utils.RedisUtils;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import java.time.Duration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -17,7 +11,16 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.time.Duration;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.sdk.enums.DeviceTypeEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.utils.RedisUtils;
/**
* 生成测试appkey与appSecret对,并存入数据库
......
......@@ -18,8 +18,11 @@ import com.wecloud.dispatch.registry.ActionBoxRegistry;
import com.wecloud.dispatch.registry.ActionInterceptorRegistry;
import com.wecloud.dispatch.registry.ActionRegistry;
import com.wecloud.dispatch.registry.MethodArgumentResolverRegistry;
import com.wecloud.dispatch.util.ActionRequestHolder;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import java.lang.reflect.InvocationTargetException;
......@@ -49,9 +52,14 @@ public class ActionDispatcher {
}
public Object action(ActionMessage am) {
// modify by luozh 2022/04/03 获取到ActionRequest后保存到ThreadLocal,便于后面业务获取
try {
ActionRequest request = getActionRequest(am);
ActionRequestHolder.setActionRequest(request);
return action(request, getArgumentBox());
} finally {
ActionRequestHolder.remove();
}
}
public Object action(ActionMessage am, ArgumentBox argumentBox) {
......
......@@ -57,7 +57,6 @@ import java.util.Set;
*/
@Controller
@ActionMapping(value = "/sendtest")
@RequestMapping("/sendtest")
@Api(value = "测试方法类", tags = {"websocket报文-全部采用json传输"})
@Slf4j
public class WsTestAction {
......@@ -73,7 +72,6 @@ public class WsTestAction {
*/
@ActionMapping(value = "gogo")
@ApiOperation(value = "测试方法")
@PostMapping("gogo")
@ApiImplicitParams({
@ApiImplicitParam(name="reqId", value = "请求id", required = false),
@ApiImplicitParam(name="hello", value = "测试参数hello", required = true),
......
package com.wecloud.dispatch.annotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -10,17 +15,47 @@ import java.lang.annotation.Target;
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@RequestMapping(method = RequestMethod.POST)
public @interface ActionMapping {
@AliasFor(annotation = RequestMapping.class)
String name() default "";
/**
* Alias for {@link RequestMapping#value}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] value() default {};
/**
* Alias for {@link RequestMapping#path}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] path() default {};
/**
* Mapping映射字段
* @return
* Alias for {@link RequestMapping#params}.
*/
String[] value() default "";
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
/**
*
* @return
* Alias for {@link RequestMapping#headers}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {};
/**
* Alias for {@link RequestMapping#consumes}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {};
/**
* Alias for {@link RequestMapping#produces}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {};
int order() default 10;
}
package com.wecloud.dispatch.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.ControllerAdviceBean;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author luozh
*/
@Slf4j
public class ActionExceptionResolver implements ApplicationContextAware, InitializingBean {
private ApplicationContext applicationContext;
private final List<Object> responseBodyAdvice = new ArrayList<>();
private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache =
new ConcurrentHashMap<>(64);
private final Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache =
new LinkedHashMap<>();
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBodyAdvice beans
initExceptionHandlerAdviceCache();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Nullable
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
private void initExceptionHandlerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
if (resolver.hasExceptionMappings()) {
this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
this.responseBodyAdvice.add(adviceBean);
}
}
if (log.isDebugEnabled()) {
int handlerSize = this.exceptionHandlerAdviceCache.size();
int adviceSize = this.responseBodyAdvice.size();
if (handlerSize == 0 && adviceSize == 0) {
log.debug("ControllerAdvice beans: none");
} else {
log.debug("ControllerAdvice beans: " +
handlerSize + " @ExceptionHandler, " + adviceSize + " ResponseBodyAdvice");
}
}
}
@Nullable
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
}
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
try {
if (log.isDebugEnabled()) {
log.debug("Using @ExceptionHandler " + exceptionHandlerMethod);
}
Throwable cause = exception.getCause();
if (cause != null) {
// Expose cause as provided argument as well
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
} else {
// Otherwise, just the given exception as-is
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
}
} catch (Throwable invocationEx) {
// Any other than the original exception (or its cause) is unintended here,
// probably an accident (e.g. failed assertion or the like).
if (invocationEx != exception && invocationEx != exception.getCause() && log.isWarnEnabled()) {
log.warn("Failure in @ExceptionHandler " + exceptionHandlerMethod, invocationEx);
}
// Continue with default processing of the original exception...
return null;
}
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
} else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
}
@Nullable
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
@Nullable HandlerMethod handlerMethod, Exception exception) {
Class<?> handlerType = null;
if (handlerMethod != null) {
// Local exception handler methods on the controller class itself.
// To be invoked through the proxy, even in case of an interface-based proxy.
handlerType = handlerMethod.getBeanType();
ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType);
if (resolver == null) {
resolver = new ExceptionHandlerMethodResolver(handlerType);
this.exceptionHandlerCache.put(handlerType, resolver);
}
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);
}
// For advice applicability check below (involving base packages, assignable types
// and annotation presence), use target class instead of interface-based proxy.
if (Proxy.isProxyClass(handlerType)) {
handlerType = AopUtils.getTargetClass(handlerMethod.getBean());
}
}
for (Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) {
ControllerAdviceBean advice = entry.getKey();
if (advice.isApplicableToBeanType(handlerType)) {
ExceptionHandlerMethodResolver resolver = entry.getValue();
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(advice.resolveBean(), method);
}
}
}
return null;
}
}
package com.wecloud.dispatch.general;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.exception.DaoException;
import io.geekidea.springbootplus.framework.common.exception.SpringBootPlusException;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import com.wecloud.dispatch.common.BaseRequest;
import com.wecloud.dispatch.extend.ActionMessage;
import com.wecloud.dispatch.extend.ArgumentBox;
import com.wecloud.dispatch.extend.impl.DefaultArgumentBox;
import com.wecloud.dispatch.general.config.GeneralActionDispatcher;
import com.wecloud.dispatch.general.extend.ActionMessageResolver;
import com.wecloud.im.exception.VerificationCodeException;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
......@@ -31,7 +39,7 @@ public class GeneralMessageHandler {
private ChannelSender channelSender;
public void doMessage(Long senderClientId, ChannelHandlerContext ctx, String data) {
if(log.isDebugEnabled()) {
if (log.isDebugEnabled()) {
log.debug("appWS收到data: {}\n senderClientId:{}, channelId:{}", data, senderClientId, ctx.channel().id().asLongText());
}
// 解析jsonO
......@@ -45,14 +53,51 @@ public class GeneralMessageHandler {
ActionMessage am = actionMessageResolver.resolver(generalActionDispatcher, baseRequest);
am.setSenderChannel(ctx.channel());
am.setSenderClientId(senderClientId);
Object res = generalActionDispatcher.action(am);
if(res != null) {
channelSender.sendMsgLocal((NioSocketChannel)am.getSenderChannel(), res);
Exception actionException = null;
Object res = null;
try {
res = generalActionDispatcher.action(am);
} catch (Exception ex) {
actionException = ex;
}
log.info("调用完成");
processDispatchResult(am, res, actionException);
}
public ArgumentBox getArgumentBox() {
ArgumentBox beanBox = new DefaultArgumentBox();
return beanBox;
}
private void processDispatchResult(ActionMessage am,
@Nullable Object res,
@Nullable Exception exception) {
log.info("处理结果");
if (exception != null) {
log.error("dispatch action error:", exception);
if (exception instanceof SpringBootPlusException) {
// 处理自定义异常
ApiCode errorCode;
if (exception instanceof BusinessException) {
errorCode = ApiCode.BUSINESS_EXCEPTION;
} else if (exception instanceof DaoException) {
errorCode = ApiCode.DAO_EXCEPTION;
} else if (exception instanceof VerificationCodeException) {
errorCode = ApiCode.VERIFICATION_CODE_EXCEPTION;
} else {
errorCode = ApiCode.SPRING_BOOT_PLUS_EXCEPTION;
}
res = WsResponse.result(errorCode, exception.getMessage(), null).setReqId(am.getMessage().getReqId());
} else {
// 其他默认的全局异常处理
res = WsResponse.result(ApiCode.SYSTEM_EXCEPTION, "", null).setReqId(am.getMessage().getReqId());
}
}
if (res != null) {
channelSender.sendMsgLocal((NioSocketChannel) am.getSenderChannel(), res);
}
}
}
......@@ -6,6 +6,7 @@ import com.wecloud.dispatch.extend.ArgumentBox;
import com.wecloud.dispatch.extend.MethodArgumentResolver;
import com.wecloud.utils.JsonUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.lang.reflect.Array;
......@@ -38,15 +39,18 @@ public class GeneralMethodArgumentResolver implements MethodArgumentResolver {
ActionRequest request,
ArgumentBox argumentBox) {
Object object = null;
RequestBody requestBodyDefine = parameter.getParameterAnnotation(RequestBody.class);
if(requestBodyDefine != null) {
Class<?> clazz = parameter.getParameterType();
object = JsonUtils.beanCopyDeep(request.getData(), clazz);
return object;
}
RequestParam define = parameter.getParameterAnnotation(RequestParam.class);
// 获取属定义的名称
String name = null == define ? parameter.getParameterName() : define.value();
Class<?> clazz = parameter.getParameterType();
Object value = request.getData().get(name);
if(ActionRequest.class.isAssignableFrom(clazz)) {
object = request;
} else if (ArgumentBox.class.isAssignableFrom(clazz)) {
......
......@@ -63,20 +63,20 @@ public class ActionRegistry {
}
}
public void add(Method method) {
if (null != method) {
Annotation[] as = method.getDeclaringClass().getAnnotations();
ActionMapping am = null;
for (Annotation annotation : as) {
if (annotation instanceof ActionMapping) {
am = ((ActionMapping) annotation);
break;
}
}
String[] codes = null == am ? new String[] { "" } : am.value();
add(codes, method);
}
}
// public void add(Method method) {
// if (null != method) {
// Annotation[] as = method.getDeclaringClass().getAnnotations();
// ActionMapping am = null;
// for (Annotation annotation : as) {
// if (annotation instanceof ActionMapping) {
// am = ((ActionMapping) annotation);
// break;
// }
// }
// String[] codes = null == am ? new String[] { "" } : am.value();
// add(codes, method);
// }
// }
public void add(String[] codes, Method method) {
if (null != method) {
......
package com.wecloud.dispatch.swagger;
import com.google.common.base.Optional;
import com.wecloud.dispatch.annotation.ActionMapping;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.condition.NameValueExpression;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spring.web.DescriptionResolver;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
public class CustomOperationPlugin implements OperationBuilderPlugin {
private final DescriptionResolver descriptions;
@Autowired
public CustomOperationPlugin(DescriptionResolver descriptions) {
this.descriptions = descriptions;
}
@Override
public void apply(OperationContext context) {
Optional<ApiOperation> apiOperationOp = context.findAnnotation(ApiOperation.class);
Optional<ActionMapping> acOp = context.findAnnotation(ActionMapping.class);
if (apiOperationOp.isPresent() || acOp.isPresent()) {
String notes = "";
if(apiOperationOp.isPresent()) {
notes = apiOperationOp.get().notes();
}
Optional<ActionMapping> hasActionMapping = context.findAnnotation(ActionMapping.class);
//添加权限码到notes中
if (hasActionMapping.isPresent()) {
notes = notes + "需要注意的是:<br/> 1、这是websocket接口;<br/> 2、请用ws://调用 <br/> 3、请求参数外层需要包一层:" +
"{ <br/>" +
"\t\"reqId\": Long类型, <br/>" +
"\t\"action\": 字符串类型(就是上面的地址) <br/>" +
"\t\"data\": 真正的请求参数(就是下面的请求参数), <br/>" +
"} ";
//编辑api文档信息, notes
context.operationBuilder().notes(descriptions.resolve(notes));
}
}
}
@Override
public boolean supports(DocumentationType documentationType) {
return SwaggerPluginSupport.pluginDoesApply(documentationType);
}
}
//package com.wecloud.dispatch.swagger;
//
//import com.fasterxml.classmate.TypeResolver;
//import com.google.common.collect.Sets;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.MediaType;
//import org.springframework.stereotype.Component;
//import springfox.documentation.builders.OperationBuilder;
//import springfox.documentation.builders.ParameterBuilder;
//import springfox.documentation.schema.ModelRef;
//import springfox.documentation.service.ApiDescription;
//import springfox.documentation.service.Operation;
//import springfox.documentation.service.Parameter;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spi.service.ApiListingScannerPlugin;
//import springfox.documentation.spi.service.contexts.DocumentationContext;
//import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;
//
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.List;
//
//@Component
//public class SwaggerAddtion implements ApiListingScannerPlugin {
// @Override
// public List<ApiDescription> apply(DocumentationContext documentationContext) {
// String path = "/oauth/token";
// String description = "UserToken";
//
// List<Parameter> parameters = new ArrayList<>();
// Parameter param1 = new ParameterBuilder()
// .description("oauth2鉴权方式,如password")//参数描述
// .type(new TypeResolver().resolve(String.class))//参数数据类型
// .name("grant_type")//参数名称
// .defaultValue("password")//参数默认值
// .parameterType("query")//参数类型
// .parameterAccess("access")
// .required(true)//是否必填
// .modelRef(new ModelRef("string")) //参数数据类型
// .build();
// parameters.add(param1);
// Parameter param2 = new ParameterBuilder()
// .description("用户名")
// .type(new TypeResolver().resolve(String.class))
// .name("username")
// .parameterType("query")
// .parameterAccess("access")
// .required(true)
// .modelRef(new ModelRef("string")) //<5>
// .build();
// parameters.add(param2);
//
// Parameter param3 = new ParameterBuilder()
// .description("密码")
// .type(new TypeResolver().resolve(String.class))
// .name("password")
// .parameterType("query")
// .parameterAccess("access")
// .required(true)
// .modelRef(new ModelRef("string")) //<5>
// .build();
// parameters.add(param3);
//
// Operation operation = new OperationBuilder(
// new CachingOperationNameGenerator())
// .method(HttpMethod.POST)//http请求类型
// .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
// .summary("获取token")
// .notes("获取token")//方法描述
// .tags(Sets.newHashSet("归类标签"))//归类标签
// .parameters(parameters)
// .build();
//
// ApiDescription apiDescription = new ApiDescription(
// path, //url
// description, //描述
// Arrays.asList(operation),
// false);
// List<ApiDescription> descriptions = new ArrayList<>();
// descriptions.add(apiDescription);
//
// return descriptions;
// }
//
// @Override
// public boolean supports(DocumentationType documentationType) {
// return DocumentationType.SWAGGER_2.equals(documentationType);
// }
//}
package com.wecloud.dispatch.util;
import com.wecloud.dispatch.extend.ActionRequest;
/**
* 记录websocket请求详情信息到当前线程中
* @Author luozh
* @Date 2022年04月03日 23:14
* @Version 1.0
*/
public class ActionRequestHolder {
private static final ThreadLocal<ActionRequest> THREAD_LOCAL = new ThreadLocal<>();
/**
* 从当前线程中获取请求信息
*/
public static ActionRequest getActionRequest() {
return THREAD_LOCAL.get();
}
public static String getReqId() {
return getActionRequest().getData().getReqId();
}
/**
* 设置请求信息到当前线程中
*
* @param actionRequest
*/
public static void setActionRequest(ActionRequest actionRequest) {
THREAD_LOCAL.set(actionRequest);
}
/**
* 销毁
*/
public static void remove() {
THREAD_LOCAL.remove();
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.log.annotation.OperationLog;
import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.ImClientBlacklistPageParam;
import com.wecloud.im.param.ImClientBlacklistQueryVo;
import com.wecloud.im.param.add.ImClientBlacklistUpdate;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.ws.model.WsResponse;
/**
* ws 黑名单
* @Author luozh
* @Date 2022年04月02日 09:20
* @Version 1.0
*/
@Slf4j
@Component
@ActionMapping(value = "/im/blacklist")
@Api(value = "ws-黑名单API", tags = {"ws-黑名单"})
public class BlacklistAction {
@Autowired
private ImClientBlacklistService imClientBlacklistService;
/**
* 添加黑名单
*/
@ActionMapping("/add")
@ApiOperation(value = "拉入黑名单")
public WsResponse<Map<String, Boolean>> addImClientBlacklist(ImClientBlacklistUpdate data) {
imClientBlacklistService.addImClientBlacklist(data);
return WsResponse.ok();
}
/**
* 删除黑名单
*/
@ActionMapping("/delete")
@ApiOperation(value = "移出黑名单")
public WsResponse<Map<String, Boolean>> deleteImClientBlacklist(ImClientBlacklistUpdate data) {
imClientBlacklistService.removeImClientBlacklist(data);
return WsResponse.ok();
}
/**
* 黑名单分页列表
* @return
*/
@ActionMapping("/getPageList")
@OperationLog(name = "黑名单分页列表", type = OperationLogType.PAGE)
@ApiOperation(value = "黑名单分页列表")
public WsResponse<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam data) {
Paging<ImClientBlacklistQueryVo> blacklist =
imClientBlacklistService.getImClientBlacklistPageList(data);
return WsResponse.ok(blacklist);
}
}
package com.wecloud.im.action;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.param.ClientInfoParam;
import com.wecloud.im.param.GetClientInfoParam;
import com.wecloud.im.param.GetOnlineStatusParam;
import com.wecloud.im.param.LogoutParam;
import com.wecloud.im.param.add.ImClientHeadPortraitAdd;
import com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate;
import com.wecloud.im.param.add.ImClientNicknameAdd;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.vo.ClientInfoVo;
import com.wecloud.im.vo.GetInfoListVo;
import com.wecloud.im.vo.ImOnlineStatusVo;
import com.wecloud.im.vo.MyInfoVo;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.im.ws.model.WsResponse;
/**
* 终端 action
* @Author luozh
* @Date 2022年04月02日 15:14
* @Version 1.0
*/
@Slf4j
@Component
@ActionMapping("/im/client")
@Api(value = "ws-终端", tags = {"ws-终端"})
public class ClientAction {
@Autowired
private ImClientService imClientService;
@Autowired
private UserStateCacheManager userStateCacheManager;
@Autowired
private ImApplicationService imApplicationService;
@Autowired
private ContextService contextService;
/**
* 查询我的信息
*/
@ActionMapping("/myInfo")
@ApiOperation(value = "查询我的信息")
public WsResponse<MyInfoVo> myInfo() {
MyInfoVo myInfo = imClientService.getMyInfo();
return WsResponse.ok(myInfo);
}
@ActionMapping("/infoList")
@ApiOperation(value = "根据id获取Client的头像昵称")
public WsResponse<Map<String, List<GetInfoListVo>>> getInfoList(GetClientInfoParam data) throws Exception {
List<GetInfoListVo> getInfoListVoList = imClientService.getInfoList(data);
Map<String, List<GetInfoListVo>> result = new HashMap<>();
result.put("result", getInfoListVoList);
return WsResponse.ok(result);
}
/**
* 查询用户信息 用户可能是好友、陌生人、被拉黑名单的人
*/
@ActionMapping("/clientInfo")
@ApiOperation(value = "查询用户信息 用户可能是好友、陌生人、被拉黑名单的人")
public WsResponse<ClientInfoVo> getClientInfo(ClientInfoParam data) {
ClientInfoVo clientInfoVo = imClientService.getClientInfo(data);
return WsResponse.ok(clientInfoVo);
}
@ActionMapping("/updateHeadAndNickname")
@ApiOperation(value = "添加或修改头像和昵称")
public WsResponse<Boolean> updateHeadAndNickname(ImClientHeadPortraitAndNicknameUpdate data) throws Exception {
log.info("添加或修改头像和昵称入参 {}", JSON.toJSONString(data));
boolean flag = imClientService.updateHeadAndNickname(data);
return WsResponse.ok(flag);
}
@ActionMapping("/updateHeadPortrait")
@ApiOperation(value = "添加或修改头像")
public WsResponse<Boolean> updateHeadPortrait(ImClientHeadPortraitAdd data) throws Exception {
log.info("添加或修改头像入参 {}", JSON.toJSONString(data));
boolean flag = imClientService.updateHeadPortrait(data);
return WsResponse.ok(flag);
}
@ActionMapping("/updateNickname")
@ApiOperation(value = "添加或修改主昵称")
public WsResponse<Boolean> updateNickname(ImClientNicknameAdd data) throws Exception {
log.info("添加或修改主昵称入参 {}", JSON.toJSONString(data));
boolean flag = imClientService.updateNickname(data);
return WsResponse.ok(flag);
}
/**
* 退出登陆
*
* @return
* @throws Exception
*/
@ActionMapping("/logout")
@ApiOperation(value = "退出登陆 清除推送token等")
public WsResponse<Map<String, Boolean>> logout(LogoutParam data) {
log.info("退出登陆入参 {}", JSON.toJSONString(data));
boolean flag = imClientService.logout(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", flag);
return WsResponse.ok(result);
}
/**
* 获取用户在线状态(批量)
*
* @return true:在线, false 不在线
*/
@ActionMapping("/onlineStatus")
@ApiOperation(value = "获取用户在线状态(批量)")
public WsResponse<List<ImOnlineStatusVo>> getOnlineStatus(
GetOnlineStatusParam data) {
// shiro线程中获取当前token
ImClient imClient = contextService.getImClientIfNotNullOrThrow();
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(imClient.getFkAppid());
List<ImOnlineStatusVo> imOnlineStatusVos = new ArrayList<>();
for (String clientId : data.getClientIds()) {
ImOnlineStatusVo imOnlineStatusVo = new ImOnlineStatusVo();
// todo 需要改成批量
ImClient client = imClientService.getCacheImClient(imApplication.getId(), clientId);
imOnlineStatusVo.setStatus(userStateCacheManager.isOnline(client.getId()));
imOnlineStatusVo.setClientId(clientId);
imOnlineStatusVos.add(imOnlineStatusVo);
}
return WsResponse.ok(imOnlineStatusVos);
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import com.alibaba.fastjson.JSON;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImConversationQueryParam;
import com.wecloud.im.param.MutedGroupMemberParam;
import com.wecloud.im.param.MutedGroupParam;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.TransferOwnerParam;
import com.wecloud.im.param.add.ImClientLeaveConversation;
import com.wecloud.im.param.add.ImClientToConversation;
import com.wecloud.im.param.add.ImConversationAttrUpdate;
import com.wecloud.im.param.add.ImConversationCreate;
import com.wecloud.im.param.add.ImConversationDisplayUpdate;
import com.wecloud.im.param.add.ImConversationNameUpdate;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.vo.ConversationVo;
import com.wecloud.im.vo.ImConversationCreateVo;
import com.wecloud.im.ws.model.WsResponse;
/**
*
* @Author luozh
* @Date 2022年04月02日 16:39
* @Version 1.0
*/
@Slf4j
@Component
@ActionMapping(value = "/im/conversation")
@Api(value = "ws-会话表API", tags = {"ws-会话表"})
public class ConversationAction {
@Autowired
private ImConversationService imConversationService;
/**
* 添加或修改会话名称
*/
@ActionMapping("/saveOrUpdateName")
@ApiOperation(value = "添加或修改会话名称", notes = "权限:目前只有创建者有权限操作")
public WsResponse<Map<String, Boolean>> saveOrUpdateName(ImConversationNameUpdate data) {
log.info("添加或修改会话名称入参 {}", JSON.toJSONString(data));
imConversationService.saveOrUpdateName(data);
return WsResponse.ok();
}
/**
* 添加或修改会话拓展字段
*/
@ActionMapping("/saveOrUpdateAttr")
@ApiOperation(value = "添加或修改会话拓展字段", notes = "权限:所有client都权限操作")
public WsResponse<Map<String, Boolean>> saveOrUpdateAttr(ImConversationAttrUpdate data) {
imConversationService.saveOrUpdateAttr(data);
return WsResponse.ok();
}
/**
* client退出会话
*/
@ActionMapping("/leave")
@ApiOperation(value = "client退出会话", notes = "若是创建者退出,[创建者]权限将会转移给按加入会话时间排序的下一个client")
public WsResponse<Map<String, Boolean>> leaveConversation(ImClientLeaveConversation data) {
log.info("client退出会话入参 {}", JSON.toJSONString(data));
imConversationService.leaveConversation(data);
return WsResponse.ok();
}
/**
* 将client从会话移除
* @return
*/
@ActionMapping("/delClient")
@ApiOperation(value = "将client从会话移除", notes = "权限:目前只有群主有权限操作")
public WsResponse<Map<String, Boolean>> delClientToConversation(ImClientToConversation data) throws Exception {
log.info("将client从会话移除入参 {}", JSON.toJSONString(data));
boolean r = imConversationService.delClientToConversation(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
* 解散群聊
*/
@ActionMapping("/disband")
@ApiOperation(value = "解散群聊", notes = "权限:目前只有群主有权限操作")
public WsResponse<Map<String, Boolean>> disband(DisbandConversationParam data) throws Exception {
log.info("解散群聊入参 {}", JSON.toJSONString(data));
imConversationService.disband(data);
return WsResponse.ok();
}
/**
* 将用户添加进会话
*/
@ActionMapping("/addClient")
@ApiOperation(value = "将用户添加进会话", notes = "权限:会话中所有client都有权限操作")
public WsResponse<Map<String, Boolean>> addClientToConversation(ImClientToConversation data) throws Exception {
log.info("将用户添加进会话入参 {}", JSON.toJSONString(data));
imConversationService.addClientToConversation(data);
return WsResponse.ok();
}
/**
* 创建会话
*/
@ActionMapping("/create")
@ApiOperation(value = "创建会话", notes = "后台可配置:两个客户端如果已经创建过会话,是否重复创建会话")
public WsResponse<ImConversationCreateVo> createImConversation(ImConversationCreate data) throws Exception {
log.info("创建会话入参 {}", JSON.toJSONString(data));
ImConversationCreateVo vo = imConversationService.createImConversation(data);
return WsResponse.ok(vo);
}
/**
* 群主转让
* @return
*/
@ActionMapping("/transferOwner")
@ApiOperation(value = "群主转让", notes = "权限:目前只有群主有权限操作")
public WsResponse<Map<String, Boolean>> transferOwner(TransferOwnerParam data) {
log.info("群主转让入参 {}", JSON.toJSONString(data));
Boolean r = imConversationService.transferOwner(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
* 设置群管理员
* @return
*/
@ActionMapping("/setAdmins")
@ApiOperation(value = "设置群管理员", notes = "权限:目前只有群主有权限操作")
public WsResponse<Map<String, Boolean>> setAdmins(@Validated SetAdminsParam data) {
log.info("设置群管理员入参 {}", JSON.toJSONString(data));
if (CollectionUtils.isEmpty(data.getClientIds())) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
Boolean r = imConversationService.setAdmins(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
* 群禁言、取消群禁言
* @return
*/
@ActionMapping("/mutedGroup")
@ApiOperation(value = "群禁言、取消群禁言", notes = "权限:群主和管理员有权限操作")
public WsResponse<Map<String, Boolean>> mutedGroup(@Validated MutedGroupParam data) {
log.info("群禁言、取消群禁言入参 {}", JSON.toJSONString(data));
Boolean r = imConversationService.mutedGroup(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
* 选择禁言
*/
@ActionMapping("/mutedGroupMember")
@ApiOperation(value = "选择禁言", notes = "权限:群主和管理员有权限操作")
public WsResponse<Map<String, Boolean>> mutedGroupMember(@Validated MutedGroupMemberParam data) {
log.info("选择禁言入参 {}", JSON.toJSONString(data));
if (CollectionUtils.isEmpty(data.getClientIds())) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
Boolean r = imConversationService.mutedGroupMember(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
* 查询用户加入的所有会话 与每个会话的未读条数 成员
* @return
*/
@ActionMapping("/getList")
@ApiOperation(value = "查询加入的会话列表", notes = "查询用户加入的非隐藏状态的会话列表 与每个会话的未读条数 成员")
public WsResponse<Map<String, List<ConversationVo>>> getMyImConversationListAndMsgCount() {
List<ConversationVo> conversationList = imConversationService.getMyImConversationListAndMsgCount();
Map<String, List<ConversationVo>> result = new HashMap<>();
result.put("result", conversationList);
return WsResponse.ok(result);
}
/**
* 根据会话id查询指定会话信息
*/
@ActionMapping("/info")
@ApiOperation(value = "根据会话id查询指定会话信息", notes = "根据会话id查询指定会话信息 与每个会话的未读条数")
public WsResponse<ConversationVo> info(@Validated ImConversationQueryParam data) throws Exception {
ConversationVo conversationVo = imConversationService.infoImConversationAndMsgCount(data);
return WsResponse.ok(conversationVo);
}
/**
* 批量修改单向隐藏或显示会话
*/
@ActionMapping("/displayUpdate")
@ApiOperation(value = "批量修改单向隐藏或显示会话", notes = "拉取会话列表不展示已隐藏状态的会话,云端聊天记录不删除;假设有A和B两个用户,A删会话,B还能发; 如果B发了消息,A这边要重新把会话显示出来,并能显示之前的聊天记录")
public WsResponse<Map<String, Boolean>> updateDisplayConversation(ImConversationDisplayUpdate data) throws Exception {
imConversationService.updateDisplayConversation(data);
return WsResponse.ok();
}
}
package com.wecloud.im.action;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.add.ImConversationMemAttrUpdate;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.ws.model.WsResponse;
/**
* @Author luozh
* @Date 2022年04月02日 16:41
* @Version 1.0
*/
@Slf4j
@Component
@ActionMapping(value = "/im/conversationMembers")
@Api(value = "ws-会话成员API", tags = {"ws-会话成员"})
public class ConversationMembersAction {
@Autowired
private ImConversationMembersService imConversationMembersService;
/**
* 添加或修改会话成员备注
* @return
*/
@ActionMapping("/updateClientRemarkName")
@ApiOperation(value = "添加或修改会话成员备注", notes = "权限:目前只有client成员自己有权限操作")
public WsResponse<Map<String, Boolean>> saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam data) throws Exception {
imConversationMembersService.saveOrUpdateClientRemarkName(data);
return WsResponse.ok();
}
/**
* 添加或修改会话成员拓展字段
*/
@ActionMapping("/updateAttr")
@ApiOperation(value = "添加或修改会话成员拓展字段", notes = "权限:目前只有client成员自己有权限操作")
public WsResponse<Map<String, Boolean>> saveOrUpdateAttr(ImConversationMemAttrUpdate data) throws Exception {
boolean r = imConversationMembersService.saveOrUpdateAttr(data);
if (r) {
return WsResponse.ok();
} else {
return WsResponse.fail();
}
}
/**
* 会话中成员表列表
* @return
*/
@ActionMapping("/getList")
@ApiOperation(value = "获取会话中成员表列表")
public WsResponse<Map<String, List<ConversationMemberVo>>> getImConversationMembersList(@Validated ListConversationMembersParam data) throws Exception {
List<ConversationMemberVo> conversationMemberVoList =
imConversationMembersService.getImConversationMembersList(data);
Map<String, List<ConversationMemberVo>> result = new HashMap<>();
result.put("result", conversationMemberVoList);
return WsResponse.ok(result);
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import com.wecloud.im.service.ImInboxService;
import com.wecloud.im.ws.model.WsResponse;
/**
* @Author luozh
* @Date 2022年04月02日 16:39
* @Version 1.0
*/
@Slf4j
@Component
@ActionMapping(value = "/im/inbox")
@Api(value = "ws-消息收件箱API", tags = {"ws-消息收件箱"})
public class InboxAction {
@Autowired
private ImInboxService imInboxService;
/**
* 消息修改为已接收状态
*/
@ActionMapping("/msgReceivedUpdate")
@ApiOperation(value = "消息修改为已接收状态")
public WsResponse<Map<String, Boolean>> updateImMsgReceived(@Validated ImMsgReceivedStatusUpdate data) throws Exception {
imInboxService.updateImMsgReceived(data);
return WsResponse.ok();
}
/**
* 消息修改为已读状态
*/
@ActionMapping("/msgReadUpdate")
@ApiOperation(value = "消息修改为已读状态")
public WsResponse<Map<String, Boolean>> updateInMsgReadUpdate(MsgReadStatusUpdateParam data) throws Exception {
if (CollectionUtils.isEmpty(data.getMsgIds())) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION);
}
imInboxService.updateImMsgRead(data);
return WsResponse.ok();
}
/**
* 会话消息修改为已读状态
* @return
*/
@ActionMapping("/updateMsgReadStatusByConversation")
@ApiOperation(value = "会话消息修改为已读状态")
public WsResponse<Map<String, Boolean>> updateMsgReadStatusByConversation(UpdateMsgReadStatusByConversationParam data) throws Exception {
if (data.getConversationId() == null) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION);
}
boolean r = imInboxService.updateMsgReadStatusByConversation(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
......@@ -12,12 +22,6 @@ import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Author wenzhida
......@@ -26,15 +30,13 @@ import org.springframework.stereotype.Component;
*/
@Slf4j
@Component
@ActionMapping(value = "/imMessage")
@ActionMapping(value = "/im/message")
@Api(value = "ws-消息API", tags = {"ws-消息"})
public class MessageAction {
@Autowired
private ImMessageService imMessageService;
@Autowired
private ChannelSender channelSender;
/**
* 消息撤回
* @param request
......@@ -42,11 +44,13 @@ public class MessageAction {
* @param reqId
*/
@ActionMapping("/withdraw")
public void withdraw(ActionRequest request, ImMsgRecall msgRecall, String reqId) {
log.info("撤回消息内容:{}", JSON.toJSONString(msgRecall));
WsResponse<Boolean> wsResponse = new WsResponse<>();
wsResponse.setData(imMessageService.withdrawMsg(request, msgRecall));
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), wsResponse);
@ApiOperation("消息撤回")
public WsResponse<Map<String, Boolean>> withdraw(ImMsgRecall data) {
log.info("撤回消息内容:{}", JSON.toJSONString(data));
Boolean r = imMessageService.withdrawMsg(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
......@@ -56,11 +60,13 @@ public class MessageAction {
* @param reqId
*/
@ActionMapping("/delete")
public void deleteMsg(ActionRequest request, MsgDeleteParam msgDeleteParam, String reqId) {
log.info("删除消息内容:{}", JSON.toJSONString(msgDeleteParam));
WsResponse<Boolean> wsResponse = new WsResponse<>();
wsResponse.setData(imMessageService.deleteMsg(request, msgDeleteParam));
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), wsResponse);
@ApiOperation("删除消息内容")
public WsResponse<Map<String, Boolean>> deleteMsg(MsgDeleteParam data) {
log.info("删除消息内容:{}", JSON.toJSONString(data));
boolean r = imMessageService.deleteMsg(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
......@@ -70,11 +76,13 @@ public class MessageAction {
* @param reqId
*/
@ActionMapping("/updateMsgById")
public void updateMsgById(ActionRequest request, ImMsgUpdate imMsgUpdate, String reqId) {
log.info("修改消息内容:{}", JSON.toJSONString(imMsgUpdate));
WsResponse<Boolean> wsResponse = new WsResponse<>();
wsResponse.setData(imMessageService.updateMsgById(imMsgUpdate));
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), wsResponse);
@ApiOperation("修改消息体")
public WsResponse<Map<String, Boolean>> updateMsgById(ImMsgUpdate data) {
log.info("修改消息内容:{}", JSON.toJSONString(data));
boolean r = imMessageService.updateMsgById(data);
Map<String, Boolean> result = new HashMap<>();
result.put("result", r);
return WsResponse.ok(result);
}
/**
......@@ -82,13 +90,13 @@ public class MessageAction {
* @param request
* @param param
* @param reqId
* @return
*/
@ActionMapping("/getHistoryMsg")
public void getHistoryMsg(ActionRequest request, ImHistoryMessagePageParam param, String reqId) {
log.info("查询某个会话历史消息分页列表:{}", JSON.toJSONString(param));
WsResponse<Paging<OfflineMsgDto>> wsResponse = new WsResponse<>();
wsResponse.setData(imMessageService.getHistoryMsgConversationId(param));
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), wsResponse);
@ApiOperation("查询某个会话历史消息分页列表")
public WsResponse<Paging<OfflineMsgDto>> getHistoryMsg(ImHistoryMessagePageParam data) {
log.info("查询某个会话历史消息分页列表:{}", JSON.toJSONString(data));
return WsResponse.ok(imMessageService.getHistoryMsgConversationId(data));
}
/**
......@@ -96,13 +104,13 @@ public class MessageAction {
* @param request
* @param param
* @param reqId
* @return
*/
@ActionMapping("/getReaders")
public void getReaders(ActionRequest request, GetReadersParam param, String reqId) {
log.info("查询某个消息已读client列表和未读client:{}", JSON.toJSONString(param));
WsResponse<ReaderList> wsResponse = new WsResponse<>();
wsResponse.setData(imMessageService.getReaders(request, param));
channelSender.sendMsgLocal((NioSocketChannel)request.getSenderChannel(), wsResponse);
@ApiOperation("查询某个消息已读client列表和未读client")
public WsResponse<ReaderList> getReaders(GetReadersParam data) {
log.info("查询某个消息已读client列表和未读client:{}", JSON.toJSONString(data));
return WsResponse.ok(imMessageService.getReaders(data));
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import com.alibaba.fastjson.JSON;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.multimeet.service.MultiMeetService;
@Slf4j
@Component
@ActionMapping(value = "/im/multiMeet")
@Api(value = "ws-多人音视频通话", tags = {"ws-多人音视频通话"})
public class MultiMeetAction {
@Autowired
private MultiMeetService multiMeetService;
/**
* 邀请客户端加入
* @return
*/
@ActionMapping("/invite")
@ApiOperation(value = "邀请加入多人音视频会议", notes = "邀请加入多人音视频会议")
public WsResponse<Map<String, Boolean>> invite(@Validated InviteToMultiMeetParam data) {
log.info("邀请加入多人音视频会议入参 {}", JSON.toJSONString(data));
if (CollectionUtils.isEmpty(data.getToClients())) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION);
}
multiMeetService.invite(data);
return WsResponse.ok();
}
@ActionMapping("/reject")
@ApiOperation(value = "拒接进入会议", notes = "拒接进入会议")
public WsResponse<Map<String, Boolean>> reject(RejectToMultiMeetParam data) {
log.info("拒绝加入多人音视频会议入参 {}", JSON.toJSONString(data));
multiMeetService.reject(data);
return WsResponse.ok();
}
@ActionMapping("/agree")
@ApiOperation(value = "同意进入会议", notes = "同意进入会议")
public WsResponse<Map<String, Boolean>> agree(AgreeToMultiMeetParam data) {
log.info("同意进入多人音视频会议入参 {}", JSON.toJSONString(data));
multiMeetService.agree(data);
return WsResponse.ok();
}
@ActionMapping("/leave")
@ApiOperation(value = "主动挂断(离开会议)", notes = "主动挂断(离开会议)")
public WsResponse<Map<String, Boolean>> leave(LeaveFromMultiMeetParam data) {
log.info("主动挂断多人音视频会议入参 {}", JSON.toJSONString(data));
multiMeetService.leave(data);
return WsResponse.ok();
}
@ActionMapping("/notAnswered")
@ApiOperation(value = "未接听", notes = "未接听")
public WsResponse<Map<String, Boolean>> notAnswered(NotAnsweredMultiMeetParam data) {
log.info("多人音视频会议未接听入参 {}", JSON.toJSONString(data));
multiMeetService.notAnswered(data);
return WsResponse.ok();
}
@ActionMapping("/heartbeat")
@ApiOperation(value = "发送心跳", notes = "发送心跳")
public WsResponse<Map<String, Boolean>> heartbeat(HeartbeatMultiMeetParam data) {
multiMeetService.heartbeat(data);
return WsResponse.ok();
}
}
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.wecloud.dispatch.annotation.ActionMapping;
......@@ -11,13 +29,13 @@ import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.GroupRoleEnum;
import com.wecloud.im.enums.MutedEnum;
import com.wecloud.im.mq.MqSender;
import com.wecloud.im.param.ChatContentVo;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.param.MsgVo;
import com.wecloud.im.sdk.enums.GroupRoleEnum;
import com.wecloud.im.sdk.enums.MutedEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientService;
......@@ -32,30 +50,16 @@ import com.wecloud.pushserver.client.model.constant.MqConstant;
import com.wecloud.pushserver.client.model.dto.PushDTO;
import com.wecloud.utils.JsonUtils;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description 处理Cmd请求
* 抽象类 策略设计模式
* @Author hewei hwei1233@163.com
* @Date 2020-01-02
* @Description 普通聊天
* @Author lixiaozhong
* @Date 2022-01-27
*/
@Slf4j
@Component
@ActionMapping(value = "/chat")
@Api(value = "ws-普通聊天", tags = {"ws-普通聊天"})
public class NormalChatAction {
@Autowired
......@@ -78,6 +82,7 @@ public class NormalChatAction {
private MqSender mqSender;
@ActionMapping("/normal/send")
@ApiOperation("普通消息发送")
public void sendMsg(ActionRequest request, ChatContentVo data, String reqId) {
if (log.isDebugEnabled()) {
log.debug("接收到参数,reqId: {},\n data: {}, ", reqId, data);
......
package com.wecloud.im.action;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wecloud.dispatch.annotation.ActionMapping;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.im.sdk.enums.CallTypeEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.rtc.service.RtcService;
@Slf4j
@Component
@ActionMapping(value = "/im/rtc")
@Api(value = "ws-音视频通话", tags = {"ws-音视频通话"})
public class RtcAction {
@Autowired
private RtcService rtcService;
/**
* 创建频道,并邀请客户端加入
*/
@ActionMapping("/createAndCall")
@ApiOperation(value = "创建频道,并邀请客户端加入", notes = "创建频道,并邀请客户端加入")
public WsResponse<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam data) {
if (BaseEnum.valueOf(CallTypeEnum.class, data.getCallType()) == null) {
return WsResponse.fail(ApiCode.PARAMETER_EXCEPTION);
}
return WsResponse.ok(rtcService.createAndCall(data));
}
@ActionMapping("/join")
@ApiOperation(value = "同意进入频道", notes = "")
public WsResponse<Map<String, Boolean>> join(JoinRtcChannelParam data) {
rtcService.join(data);
return WsResponse.ok();
}
@ActionMapping("/reject")
@ApiOperation(value = "拒接进入频道", notes = "")
public WsResponse<Map<String, Boolean>> reject(RejectRtcChannelParam data) {
rtcService.reject(data);
return WsResponse.ok();
}
@ActionMapping("/leave")
@ApiOperation(value = "主动挂断(离开频道)", notes = "")
public WsResponse<Map<String, Boolean>> leave(LeaveRtcChannelParam data) {
rtcService.leave(data);
return WsResponse.ok();
}
@ActionMapping("/sdpForward")
@ApiOperation(value = "SDP数据转发", notes = "")
public WsResponse<Map<String, Boolean>> sdpForward(SdpForwardParam data) {
rtcService.sdpForward(data);
return WsResponse.ok();
}
@ActionMapping("/candidateForward")
@ApiOperation(value = "candidate候选者数据转发", notes = "")
public WsResponse<Map<String, Boolean>> candidateForward(CandidateForwardParam data) {
rtcService.candidateForward(data);
return WsResponse.ok();
}
}
package com.wecloud.im.controller;
import com.wecloud.im.param.ImClientBlacklistPageParam;
import com.wecloud.im.param.ImClientBlacklistQueryVo;
import com.wecloud.im.param.add.ImClientBlacklistUpdate;
import com.wecloud.im.service.ImClientBlacklistService;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
......@@ -13,6 +9,7 @@ import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -20,6 +17,11 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wecloud.im.param.ImClientBlacklistPageParam;
import com.wecloud.im.param.ImClientBlacklistQueryVo;
import com.wecloud.im.param.add.ImClientBlacklistUpdate;
import com.wecloud.im.service.ImClientBlacklistService;
/**
* 黑名单 控制器
*
......@@ -41,7 +43,8 @@ public class ImClientBlacklistController extends BaseController {
@PostMapping("/add")
@ApiOperation(value = "拉入黑名单")
public ApiResult<Boolean> addImClientBlacklist(@Validated(Add.class) @RequestBody ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception {
return imClientBlacklistService.addImClientBlacklist(imClientBlacklistUpdate);
imClientBlacklistService.addImClientBlacklist(imClientBlacklistUpdate);
return ApiResult.ok();
}
......@@ -51,7 +54,8 @@ public class ImClientBlacklistController extends BaseController {
@PostMapping("/delete")
@ApiOperation(value = "移出黑名单")
public ApiResult<Boolean> deleteImClientBlacklist(@RequestBody ImClientBlacklistUpdate imClientBlacklistUpdate) throws Exception {
return imClientBlacklistService.removeImClientBlacklist(imClientBlacklistUpdate);
imClientBlacklistService.removeImClientBlacklist(imClientBlacklistUpdate);
return ApiResult.ok();
}
/**
......@@ -61,7 +65,9 @@ public class ImClientBlacklistController extends BaseController {
@OperationLog(name = "黑名单分页列表", type = OperationLogType.PAGE)
@ApiOperation(value = "黑名单分页列表")
public ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(@RequestBody ImClientBlacklistPageParam imClientBlacklistPageParam) throws Exception {
return imClientBlacklistService.getImClientBlacklistPageList(imClientBlacklistPageParam);
Paging<ImClientBlacklistQueryVo> blacklist =
imClientBlacklistService.getImClientBlacklistPageList(imClientBlacklistPageParam);
return ApiResult.ok(blacklist);
}
}
......
package com.wecloud.im.controller;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.geekidea.springbootplus.framework.core.validator.groups.Add;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
......@@ -18,24 +38,6 @@ import com.wecloud.im.vo.GetInfoListVo;
import com.wecloud.im.vo.ImOnlineStatusVo;
import com.wecloud.im.vo.MyInfoVo;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.geekidea.springbootplus.framework.core.validator.groups.Add;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 终端表 控制器
......@@ -72,7 +74,7 @@ public class ImClientController extends BaseController {
@PostMapping("/infoList")
@ApiOperation(value = "根据id获取Client的头像昵称")
public ApiResult<List<GetInfoListVo>> getInfoList(@Validated(Add.class) @RequestBody GetClientInfoParam getClientInfoParam) throws Exception {
return imClientService.getInfoList(getClientInfoParam);
return ApiResult.ok(imClientService.getInfoList(getClientInfoParam));
}
/**
......@@ -81,7 +83,7 @@ public class ImClientController extends BaseController {
@PostMapping("/clientInfo")
@ApiOperation(value = "查询用户信息 用户可能是好友、陌生人、被拉黑名单的人")
public ApiResult<ClientInfoVo> getClientInfo(@RequestBody ClientInfoParam param) {
if(param == null) {
if (param == null) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
ClientInfoVo clientInfoVo = imClientService.getClientInfo(param);
......
package com.wecloud.im.controller;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImConversationQueryParam;
......@@ -16,21 +33,6 @@ import com.wecloud.im.param.add.ImConversationNameUpdate;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.vo.ConversationVo;
import com.wecloud.im.vo.ImConversationCreateVo;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 会话表 控制器
......@@ -78,7 +80,7 @@ public class ImConversationController extends BaseController {
@ApiOperation(value = "client退出会话", notes = "若是创建者退出,[创建者]权限将会转移给按加入会话时间排序的下一个client")
public ApiResult<Boolean> leaveConversation(@RequestBody ImClientLeaveConversation imClientToConversation) {
log.info("client退出会话入参 {}", JSON.toJSONString(imClientToConversation));
return imConversationService.leaveConversation(imClientToConversation);
return ApiResult.ok(imConversationService.leaveConversation(imClientToConversation));
}
......@@ -89,7 +91,7 @@ public class ImConversationController extends BaseController {
@ApiOperation(value = "将client从会话移除", notes = "权限:目前只有群主有权限操作")
public ApiResult<Boolean> delClientToConversation(@RequestBody ImClientToConversation imClientToConversation) throws Exception {
log.info("将client从会话移除入参 {}", JSON.toJSONString(imClientToConversation));
return imConversationService.delClientToConversation(imClientToConversation);
return ApiResult.ok(imConversationService.delClientToConversation(imClientToConversation));
}
/**
......@@ -111,7 +113,7 @@ public class ImConversationController extends BaseController {
@ApiOperation(value = "将用户添加进会话", notes = "权限:会话中所有client都有权限操作")
public ApiResult<Boolean> addClientToConversation(@RequestBody ImClientToConversation imClientToConversation) throws Exception {
log.info("将用户添加进会话入参 {}", JSON.toJSONString(imClientToConversation));
return imConversationService.addClientToConversation(imClientToConversation);
return ApiResult.ok(imConversationService.addClientToConversation(imClientToConversation));
}
/**
......@@ -121,7 +123,7 @@ public class ImConversationController extends BaseController {
@ApiOperation(value = "创建会话", notes = "后台可配置:两个客户端如果已经创建过会话,是否重复创建会话")
public ApiResult<ImConversationCreateVo> createImConversation(@RequestBody ImConversationCreate imConversationCreate) throws Exception {
log.info("创建会话入参 {}", JSON.toJSONString(imConversationCreate));
return imConversationService.createImConversation(imConversationCreate);
return ApiResult.ok(imConversationService.createImConversation(imConversationCreate));
}
/**
......
......@@ -51,7 +51,12 @@ public class ImConversationMembersController extends BaseController {
@PostMapping("/updateAttr")
@ApiOperation(value = "添加或修改会话成员拓展字段", notes = "权限:目前只有client成员自己有权限操作")
public ApiResult<Boolean> saveOrUpdateAttr(@RequestBody ImConversationMemAttrUpdate imConversationMemAttrUpdate) throws Exception {
return imConversationMembersService.saveOrUpdateAttr(imConversationMemAttrUpdate);
boolean r = imConversationMembersService.saveOrUpdateAttr(imConversationMemAttrUpdate);
if (r) {
return ApiResult.ok();
} else {
return ApiResult.fail();
}
}
......
......@@ -39,7 +39,8 @@ public class ImInboxController extends BaseController {
@PostMapping("/msgReceivedUpdate")
@ApiOperation(value = "消息修改为已接收状态")
public ApiResult<Boolean> updateImMsgReceived(@RequestBody @Validated ImMsgReceivedStatusUpdate imMsgReceivedUpdate) throws Exception {
return imInboxService.updateImMsgReceived(imMsgReceivedUpdate);
imInboxService.updateImMsgReceived(imMsgReceivedUpdate);
return ApiResult.ok();
}
/**
......@@ -51,7 +52,8 @@ public class ImInboxController extends BaseController {
if (CollectionUtils.isEmpty(msgReadStatusUpdateParam.getMsgIds())) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION);
}
return imInboxService.updateImMsgRead(msgReadStatusUpdateParam);
imInboxService.updateImMsgRead(msgReadStatusUpdateParam);
return ApiResult.ok();
}
/**
......
package com.wecloud.im.controller;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
......@@ -18,6 +9,9 @@ import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
......@@ -26,7 +20,15 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import com.wecloud.im.param.GetReadersParam;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
/**
* 消息存储表 控制器
......@@ -49,7 +51,7 @@ public class ImMessageController extends BaseController {
@PostMapping("/withdraw")
@ApiOperation(value = "消息撤回", notes = "只能撤回客户端自己发送的消息")
public ApiResult<Boolean> withdrawMsg(@RequestBody ImMsgRecall imMsgRecall) throws Exception {
return ApiResult.ok(imMessageService.withdrawMsg(null, imMsgRecall));
return ApiResult.ok(imMessageService.withdrawMsg(imMsgRecall));
}
/**
......@@ -64,7 +66,7 @@ public class ImMessageController extends BaseController {
if (CollectionUtils.isEmpty(param.getMsgIds())) {
return ApiResult.fail("请选择要删除的消息id");
}
return ApiResult.ok(imMessageService.deleteMsg(null, param));
return ApiResult.ok(imMessageService.deleteMsg(param));
}
/**
......@@ -103,7 +105,7 @@ public class ImMessageController extends BaseController {
@PostMapping("/getReaders")
@ApiOperation(value = "查询某个消息已读client列表和未读client")
public ApiResult<ReaderList> getReaders(@Validated @RequestBody GetReadersParam param) {
ReaderList readerList = imMessageService.getReaders(null, param);
ReaderList readerList = imMessageService.getReaders(param);
return ApiResult.ok(readerList);
}
......
......@@ -2,8 +2,10 @@ package com.wecloud.im.controller;
import com.alibaba.fastjson.JSON;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.multimeet.service.MultiMeetService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
......@@ -59,6 +61,7 @@ public class ImMultiMeetController extends BaseController {
@PostMapping("/agree")
@ApiOperation(value = "同意进入会议", notes = "同意进入会议")
public ApiResult<Boolean> agree(@RequestBody AgreeToMultiMeetParam param) {
log.info("同意进入多人音视频会议入参 {}", JSON.toJSONString(param));
multiMeetService.agree(param);
return ApiResult.ok();
}
......@@ -66,9 +69,25 @@ public class ImMultiMeetController extends BaseController {
@PostMapping("/leave")
@ApiOperation(value = "主动挂断(离开会议)", notes = "主动挂断(离开会议)")
public ApiResult<Boolean> leave(@RequestBody LeaveFromMultiMeetParam param) {
log.info("主动挂断多人音视频会议入参 {}", JSON.toJSONString(param));
multiMeetService.leave(param);
return ApiResult.ok();
}
@PostMapping("/notAnswered")
@ApiOperation(value = "未接听", notes = "未接听")
public ApiResult<Boolean> notAnswered(@RequestBody NotAnsweredMultiMeetParam param) {
log.info("多人音视频会议未接听入参 {}", JSON.toJSONString(param));
multiMeetService.notAnswered(param);
return ApiResult.ok();
}
@PostMapping("/heartbeat")
@ApiOperation(value = "发送心跳", notes = "发送心跳")
public ApiResult<Boolean> heartbeat(@RequestBody HeartbeatMultiMeetParam param) {
multiMeetService.heartbeat(param);
return ApiResult.ok();
}
}
package com.wecloud.im.controller;
import com.wecloud.im.enums.CallTypeEnum;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.rtc.service.RtcService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
......@@ -16,12 +7,23 @@ import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.im.sdk.enums.CallTypeEnum;
import com.wecloud.rtc.service.RtcService;
/**
* 音视频通话 控制器
*
......@@ -46,41 +48,46 @@ public class ImRtcController extends BaseController {
if (BaseEnum.valueOf(CallTypeEnum.class, createRtcChannelParam.getCallType()) == null) {
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
}
return rtcService.createAndCall(createRtcChannelParam);
return ApiResult.ok(rtcService.createAndCall(createRtcChannelParam));
}
@PostMapping("/join")
@ApiOperation(value = "同意进入频道", notes = "")
public ApiResult<Boolean> join(@RequestBody JoinRtcChannelParam joinRtcChannelParam) {
return rtcService.join(joinRtcChannelParam);
rtcService.join(joinRtcChannelParam);
return ApiResult.ok();
}
@PostMapping("/reject")
@ApiOperation(value = "拒接进入频道", notes = "")
public ApiResult<Boolean> reject(@RequestBody RejectRtcChannelParam rejectRtcChannelParam) {
return rtcService.reject(rejectRtcChannelParam);
rtcService.reject(rejectRtcChannelParam);
return ApiResult.ok();
}
@PostMapping("/leave")
@ApiOperation(value = "主动挂断(离开频道)", notes = "")
public ApiResult<Boolean> leave(@RequestBody LeaveRtcChannelParam leaveRtcChannelParam) {
return rtcService.leave(leaveRtcChannelParam);
rtcService.leave(leaveRtcChannelParam);
return ApiResult.ok();
}
@PostMapping("/sdpForward")
@ApiOperation(value = "SDP数据转发", notes = "")
public ApiResult<Boolean> sdpForward(@RequestBody SdpForwardParam sdpForwardParam) {
return rtcService.sdpForward(sdpForwardParam);
rtcService.sdpForward(sdpForwardParam);
return ApiResult.ok();
}
@PostMapping("/candidateForward")
@ApiOperation(value = "candidate候选者数据转发", notes = "")
public ApiResult<Boolean> candidateForward(@RequestBody CandidateForwardParam candidateForwardParam) {
return rtcService.candidateForward(candidateForwardParam);
rtcService.candidateForward(candidateForwardParam);
return ApiResult.ok();
}
......
package com.wecloud.im.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,9 +7,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* 会话表
*
......@@ -64,7 +66,7 @@ public class ImConversation extends BaseEntity {
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
package com.wecloud.im.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,9 +7,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* 会话成员表
*
......@@ -60,14 +62,14 @@ public class ImConversationMembers extends BaseEntity {
/**
* 群内角色
* @see com.wecloud.im.enums.GroupRoleEnum
* @see com.wecloud.im.sdk.enums.GroupRoleEnum
*/
@ApiModelProperty("群内角色")
private Integer role;
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
package com.wecloud.im.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,9 +7,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* @Author wenzhida
* @Date 2022/3/15 23:09
......@@ -38,7 +40,7 @@ public class ImMultiRtcRoom extends BaseEntity {
/**
* 多人音视频房间状态枚举
* @see com.wecloud.im.enums.MultiRtcRoomStateEnum
* @see com.wecloud.im.sdk.enums.MultiRtcRoomStateEnum
*/
@ApiModelProperty("房间状态,1:已创建,2:会议中,3:会议结束")
private Integer state;
......
package com.wecloud.im.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,9 +7,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* @Author wenzhida
* @Date 2022/3/15 23:09
......@@ -44,7 +46,7 @@ public class ImMultiRtcRoomMember extends BaseEntity {
/**
* 多人音视频房间成员状态枚举
* @see com.wecloud.im.enums.MultiRtcMemberStateEnum
* @see com.wecloud.im.sdk.enums.MultiRtcMemberStateEnum
*/
@ApiModelProperty("房间成员状态,1:呼叫中,2:已接听,3:已拒绝,4:未接听,5:已断开")
private Integer state;
......@@ -52,6 +54,9 @@ public class ImMultiRtcRoomMember extends BaseEntity {
@ApiModelProperty("呼叫时间")
private Date callTime;
@ApiModelProperty("心跳时间")
private Date heartbeatTime;
@ApiModelProperty("创建时间")
private Date createTime;
......
package com.wecloud.im.externalaccess.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.enums.VerifySceneEnum;
import com.wecloud.im.constant.RedisKeyPrefixConstant;
import com.wecloud.im.externalaccess.entity.User;
import com.wecloud.im.externalaccess.param.SendVerifyCodeParam;
import com.wecloud.im.externalaccess.service.UserService;
import com.wecloud.im.ws.utils.RedisUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
......@@ -15,6 +8,9 @@ import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -22,7 +18,13 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.constant.RedisKeyPrefixConstant;
import com.wecloud.im.externalaccess.entity.User;
import com.wecloud.im.externalaccess.param.SendVerifyCodeParam;
import com.wecloud.im.externalaccess.service.UserService;
import com.wecloud.im.sdk.enums.VerifySceneEnum;
import com.wecloud.im.ws.utils.RedisUtils;
/**
* @Author wenzhida
......
......@@ -3,9 +3,10 @@ package com.wecloud.im.externalaccess.param;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
/**
* @Author wenzhida
* @Date 2022/2/23 15:20
......@@ -25,7 +26,7 @@ public class ModifySexParam implements Serializable {
/**
* 性别
* @see com.wecloud.im.enums.SexEnum
* @see com.wecloud.im.sdk.enums.SexEnum
*/
@NotNull(message = "性别不可为空不可为空")
@ApiModelProperty("性别 1-男 2-女 3-未知")
......
......@@ -3,9 +3,10 @@ package com.wecloud.im.externalaccess.param;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
/**
* @Author wenzhida
* @Date 2022/2/21 18:15
......@@ -25,7 +26,7 @@ public class SendVerifyCodeParam implements Serializable {
/**
* 验证场景 1-用户注册 2-重置密码验证 3-更换手机号绑定
* @see com.wecloud.im.enums.VerifySceneEnum
* @see com.wecloud.im.sdk.enums.VerifySceneEnum
*/
@NotNull(message = "验证场景不可为空")
@ApiModelProperty("验证场景 1-用户注册 2-重置密码验证 3-更换手机号绑定")
......
......@@ -29,7 +29,7 @@ public class UserBaseDto implements Serializable {
/**
* 性别
* @see com.wecloud.im.enums.SexEnum
* @see com.wecloud.im.sdk.enums.SexEnum
*/
@ApiModelProperty("性别 1-男 2-女 3-未知")
private Integer sex;
......@@ -45,7 +45,7 @@ public class UserBaseDto implements Serializable {
/**
* 与我关系
* @see com.wecloud.im.enums.RelationEnum
* @see com.wecloud.im.sdk.enums.RelationEnum
*/
@ApiModelProperty("与我关系 1-陌生人 2-好友 3-被我拉黑")
private Integer relation;
......
package com.wecloud.im.externalaccess.param;
import com.wecloud.im.enums.DeviceTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import com.wecloud.im.sdk.enums.DeviceTypeEnum;
/**
* @Author wenzhida
* @Date 2022/2/21 18:15
......
package com.wecloud.im.externalaccess.service;
import cn.hutool.core.lang.Snowflake;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import java.util.Date;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.constant.NumberConstant;
import com.wecloud.im.constant.RedisKeyPrefixConstant;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImClientDevice;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.enums.RelationEnum;
import com.wecloud.im.enums.VerifySceneEnum;
import com.wecloud.im.externalaccess.entity.User;
import com.wecloud.im.externalaccess.mapper.UserMapper;
import com.wecloud.im.externalaccess.param.ChangePhoneParam;
......@@ -29,6 +35,9 @@ import com.wecloud.im.friend.entity.ImFriend;
import com.wecloud.im.friend.service.ImFriendService;
import com.wecloud.im.param.add.ImClientHeadPortraitAdd;
import com.wecloud.im.param.add.ImClientNicknameUpdate;
import com.wecloud.im.sdk.enums.FriendStateEnum;
import com.wecloud.im.sdk.enums.RelationEnum;
import com.wecloud.im.sdk.enums.VerifySceneEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientDeviceService;
......@@ -37,14 +46,6 @@ import com.wecloud.im.ws.utils.RedisUtils;
import com.wecloud.utils.AesUtil;
import com.wecloud.utils.RandomUtil;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
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.Date;
/**
* @Author wenzhida
......
package com.wecloud.im.friend.controller;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.friend.param.ImCreateRecommendParam;
import com.wecloud.im.friend.param.ImDeleteFriendParam;
import com.wecloud.im.friend.param.ImDeleteRecommendParam;
import com.wecloud.im.friend.param.ImFriendApplyDto;
import com.wecloud.im.friend.param.ImFriendApplyParam;
import com.wecloud.im.friend.param.ImFriendApproveParam;
import com.wecloud.im.friend.param.ImFriendBaseDto;
import com.wecloud.im.friend.param.ImFriendBaseParam;
import com.wecloud.im.friend.param.ImFriendPageParam;
import com.wecloud.im.friend.param.ImFriendRecommendDto;
import com.wecloud.im.friend.service.ImFriendService;
import com.wecloud.im.service.ImClientService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.controller.BaseController;
......@@ -24,6 +10,9 @@ import io.geekidea.springbootplus.framework.log.enums.OperationLogType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -31,7 +20,20 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.friend.param.ImCreateRecommendParam;
import com.wecloud.im.friend.param.ImDeleteFriendParam;
import com.wecloud.im.friend.param.ImDeleteRecommendParam;
import com.wecloud.im.friend.param.ImFriendApplyDto;
import com.wecloud.im.friend.param.ImFriendApplyParam;
import com.wecloud.im.friend.param.ImFriendApproveParam;
import com.wecloud.im.friend.param.ImFriendBaseDto;
import com.wecloud.im.friend.param.ImFriendBaseParam;
import com.wecloud.im.friend.param.ImFriendPageParam;
import com.wecloud.im.friend.param.ImFriendRecommendDto;
import com.wecloud.im.friend.service.ImFriendService;
import com.wecloud.im.sdk.enums.FriendStateEnum;
import com.wecloud.im.service.ImClientService;
/**
* @author lixiaozhong
......
package com.wecloud.im.friend.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,9 +7,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* @author lixiaozhong
* 好友关系表
......@@ -48,7 +50,7 @@ public class ImFriend extends BaseEntity {
/**
* 好友关系状态
* @see com.wecloud.im.enums.FriendStateEnum
* @see com.wecloud.im.sdk.enums.FriendStateEnum
*/
@ApiModelProperty("好友关系状态")
private Integer state;
......
......@@ -14,7 +14,7 @@ import java.io.Serializable;
public class FriendBaseEventDto implements Serializable {
/**
* 参考 {@link com.wecloud.im.enums.EventResponseSubCmdEnum EventResponseSubCmdEnum}
* 参考 {@link com.wecloud.im.sdk.enums.EventResponseSubCmdEnum EventResponseSubCmdEnum}
*/
@ApiModelProperty("响应命令")
private Integer subCmd;
......
package com.wecloud.im.friend.service;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.EventResponseSubCmdEnum;
import com.wecloud.im.friend.param.FriendApplyEventDto;
import com.wecloud.im.friend.param.FriendApproveEventDto;
import com.wecloud.im.mq.MqSender;
import com.wecloud.im.sdk.enums.EventResponseSubCmdEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
......@@ -13,10 +19,6 @@ import com.wecloud.im.ws.model.request.PushVO;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.pushserver.client.model.constant.MqConstant;
import com.wecloud.pushserver.client.model.dto.PushDTO;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Description TODO
......
package com.wecloud.im.friend.service;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
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 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.friend.entity.ImFriend;
import com.wecloud.im.friend.entity.ImFriendRecommend;
import com.wecloud.im.friend.mapper.ImFriendMapper;
......@@ -16,23 +31,9 @@ import com.wecloud.im.friend.param.ImFriendBaseDto;
import com.wecloud.im.friend.param.ImFriendPageParam;
import com.wecloud.im.friend.param.ImFriendRecommendDto;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.sdk.enums.FriendStateEnum;
import com.wecloud.im.service.ImClientService;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import com.wecloud.utils.SnowflakeUtil;
import org.apache.commons.collections4.CollectionUtils;
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.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description 好友关系处理逻辑
......@@ -106,6 +107,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
} else {
my.setId(SnowflakeUtil.getId());
my.setCreateTime(new Date());
my.setUpdateTime(new Date());
this.save(my);
}
......@@ -123,6 +125,7 @@ public class ImFriendService extends BaseServiceImpl<ImFriendMapper, ImFriend> {
} else {
friend.setId(SnowflakeUtil.getId());
friend.setCreateTime(new Date());
friend.setUpdateTime(new Date());
this.save(friend);
}
......
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/4/1 20:09
* @Description 多人音视频会议发送心跳入参
*/
@Data
@ApiModel(value = "多人音视频会议发送心跳入参")
public class HeartbeatMultiMeetParam implements Serializable {
private static final long serialVersionUID = -5000410376842426276L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
}
......@@ -57,7 +57,7 @@ public class ImConversationQueryVo implements Serializable {
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
......@@ -31,7 +31,7 @@ public class ListConversationMembersParam implements Serializable {
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
......@@ -4,8 +4,6 @@ import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
......@@ -22,7 +20,7 @@ public class LogoutParam extends BaseEntity {
/**
* 设备类型
* @see com.wecloud.im.enums.DeviceTypeEnum
* @see com.wecloud.im.sdk.enums.DeviceTypeEnum
*/
@ApiModelProperty("设备类型 1:ios; 2:android; 3:web; 4:win; 5:mac")
@NotNull(message = "设备类型不能为空")
......
package com.wecloud.im.param;
import com.wecloud.im.enums.MutedEnum;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -27,7 +26,7 @@ public class MutedGroupParam extends BaseEntity {
/**
* 禁言类型
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@NotNull
@ApiModelProperty("禁言类型 1-取消禁言 2-禁言")
......
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/3/24 11:06
* @Description 未接听入参
*/
@Data
@ApiModel(value = "未接听入参")
public class NotAnsweredMultiMeetParam implements Serializable {
private static final long serialVersionUID = 7439324829502466053L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
}
......@@ -25,7 +25,7 @@ public class ClientDeviceUpdateParam extends BaseEntity {
/**
* 设备类型
* @see com.wecloud.im.enums.DeviceTypeEnum
* @see com.wecloud.im.sdk.enums.DeviceTypeEnum
*/
@ApiModelProperty("设备类型 1:ios; 2:android; 3:web; 4:win; 5:mac")
private Integer deviceType;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import lombok.AllArgsConstructor;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import lombok.AllArgsConstructor;
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import lombok.AllArgsConstructor;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import lombok.AllArgsConstructor;
......
package com.wecloud.im.enums;
package com.wecloud.im.sdk.enums;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
......
package com.wecloud.im.service;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
/**
* 请求上下文服务
* @Author luozh
* @Date 2022年04月02日 14:51
* @Version 1.0
*/
public interface ContextService {
/**
* 获取当前或指定clientId的ImClient 存在返回 不存在则抛出异常
* @Author luozh
* @Date 2022年04月02日 02:52:09
* @param request Ws请求
* @Return
*/
ImClient getImClientIfNotNullOrThrow();
/**
* 获取当前或指定appId的ImApplication 存在返回 不存在则抛出异常
* @Author luozh
* @Date 2022年04月02日 02:54:21
* @param appId 应用id
* @Return
*/
ImApplication getImApplicationIfNotNullOrThrow(Long appId);
}
package com.wecloud.im.service;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.im.entity.ImClientBlacklist;
import com.wecloud.im.param.ImClientBlacklistPageParam;
import com.wecloud.im.param.ImClientBlacklistQueryVo;
import com.wecloud.im.param.add.ImClientBlacklistUpdate;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
/**
* 黑名单 服务类
......@@ -33,7 +34,7 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
Boolean addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
/**
* 移出黑名单
......@@ -42,7 +43,7 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
Boolean removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate);
/**
* 获取分页对象
......@@ -50,6 +51,6 @@ public interface ImClientBlacklistService extends BaseService<ImClientBlacklist>
* @return
* @throws Exception
*/
ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam);
Paging<ImClientBlacklistQueryVo> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam);
}
package com.wecloud.im.service;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import java.util.List;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.param.ClientInfoParam;
import com.wecloud.im.param.GetClientInfoParam;
......@@ -15,11 +22,6 @@ import com.wecloud.im.param.add.ImClientNicknameUpdate;
import com.wecloud.im.vo.ClientInfoVo;
import com.wecloud.im.vo.GetInfoListVo;
import com.wecloud.im.vo.MyInfoVo;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import java.util.List;
/**
* 终端表 服务类
......@@ -59,7 +61,7 @@ public interface ImClientService extends BaseService<ImClient> {
* @return
* @throws Exception
*/
ApiResult<List<GetInfoListVo>> getInfoList(GetClientInfoParam getClientInfoParam) throws Exception;
List<GetInfoListVo> getInfoList(GetClientInfoParam getClientInfoParam) throws Exception;
/**
* 获取群里成员信息
......@@ -103,7 +105,7 @@ public interface ImClientService extends BaseService<ImClient> {
* @return
* @throws Exception
*/
boolean updateImClient(ImClient imClient) throws Exception;
boolean updateImClient( ImClient imClient) throws Exception;
/**
* 删除
......@@ -112,7 +114,7 @@ public interface ImClientService extends BaseService<ImClient> {
* @return
* @throws Exception
*/
boolean deleteImClient(Long id) throws Exception;
boolean deleteImClient( Long id) throws Exception;
/**
* 获取分页对象
......
......@@ -2,13 +2,7 @@ package com.wecloud.im.service;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.param.ApiImConversationMembersPageParam;
import com.wecloud.im.param.ApiImConversationMembersQueryVo;
import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.ImConversationMembersPageParam;
import com.wecloud.im.param.ImConversationMembersQueryVo;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.*;
import com.wecloud.im.param.add.ImConversationMemAttrUpdate;
import com.wecloud.im.vo.ConversationMemberVo;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
......@@ -54,7 +48,7 @@ public interface ImConversationMembersService extends BaseService<ImConversation
List<ConversationMemberVo> getImConversationMembersList(ListConversationMembersParam param);
ApiResult<Boolean> saveOrUpdateAttr(ImConversationMemAttrUpdate imConversationMemAttrUpdate);
Boolean saveOrUpdateAttr(ImConversationMemAttrUpdate imConversationMemAttrUpdate);
/**
* 保存
......
package com.wecloud.im.service;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.param.DisbandConversationParam;
......@@ -16,14 +22,8 @@ import com.wecloud.im.param.add.ImConversationAttrUpdate;
import com.wecloud.im.param.add.ImConversationCreate;
import com.wecloud.im.param.add.ImConversationDisplayUpdate;
import com.wecloud.im.param.add.ImConversationNameUpdate;
import com.wecloud.im.vo.ImConversationCreateVo;
import com.wecloud.im.vo.ConversationVo;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import com.wecloud.im.vo.ImConversationCreateVo;
/**
* 会话表 服务类
......@@ -49,7 +49,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @param imConversationCreate
* @return
*/
ApiResult<ImConversationCreateVo> createImConversation(ImConversationCreate imConversationCreate);
ImConversationCreateVo createImConversation(ImConversationCreate imConversationCreate);
/**
......@@ -59,7 +59,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @return
* @throws JsonProcessingException
*/
ApiResult<Boolean> addClientToConversation(ImClientToConversation imClientToConversation);
Boolean addClientToConversation(ImClientToConversation imClientToConversation);
/**
* 将client从会话移除
......@@ -67,7 +67,7 @@ public interface ImConversationService extends BaseService<ImConversation> {
* @param imClientToConversation
* @return
*/
ApiResult<Boolean> delClientToConversation(ImClientToConversation imClientToConversation) throws Exception;
Boolean delClientToConversation(ImClientToConversation imClientToConversation) throws Exception;
/**
* 解散群聊
......@@ -79,35 +79,35 @@ public interface ImConversationService extends BaseService<ImConversation> {
/**
* client退出会话
*/
ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation);
Boolean leaveConversation(ImClientLeaveConversation imClientToConversation);
/**
* 群主转让
* @param param
* @return
*/
Boolean transferOwner(@RequestBody TransferOwnerParam param);
Boolean transferOwner(TransferOwnerParam param);
/**
* 设置管理员
* @param param
* @return
*/
Boolean setAdmins(@RequestBody SetAdminsParam param);
Boolean setAdmins(SetAdminsParam param);
/**
* 群禁言
* @param param
* @return
*/
Boolean mutedGroup(@RequestBody MutedGroupParam param);
Boolean mutedGroup(MutedGroupParam param);
/**
* 选择禁言
* @param param
* @return
*/
Boolean mutedGroupMember(@RequestBody MutedGroupMemberParam param);
Boolean mutedGroupMember(MutedGroupMemberParam param);
/**
* 判断当前操作人是否为指定角色成员
......
......@@ -2,10 +2,9 @@ package com.wecloud.im.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
/**
......@@ -68,7 +67,7 @@ public interface ImInboxService extends BaseService<ImInbox> {
* @param imMsgReceivedUpdate
* @return
*/
ApiResult<Boolean> updateImMsgReceived(ImMsgReceivedStatusUpdate imMsgReceivedUpdate);
Boolean updateImMsgReceived(ImMsgReceivedStatusUpdate imMsgReceivedUpdate);
/**
* 统计未读消息数量
......@@ -83,7 +82,7 @@ public interface ImInboxService extends BaseService<ImInbox> {
*
* @return
*/
ApiResult<Boolean> updateImMsgRead(MsgReadStatusUpdateParam msgReadStatusUpdateParam) throws JsonProcessingException;
Boolean updateImMsgRead(MsgReadStatusUpdateParam msgReadStatusUpdateParam) throws JsonProcessingException;
/**
* 整个会话消息修改为已读状态
......
package com.wecloud.im.service;
import com.wecloud.dispatch.extend.ActionRequest;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMessage;
......@@ -17,12 +24,6 @@ import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.vo.ReaderList;
import com.wecloud.im.ws.model.request.ReceiveDataVO;
import com.wecloud.im.ws.model.request.ReceiveVO;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.BaseService;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 消息存储表 服务类
......@@ -54,14 +55,14 @@ public interface ImMessageService extends BaseService<ImMessage> {
* @param request
* @return
*/
Boolean withdrawMsg(ActionRequest request, ImMsgRecall imMsgRecall);
Boolean withdrawMsg(ImMsgRecall imMsgRecall);
/**
* 删除消息
* @param param
* @return
*/
Boolean deleteMsg(ActionRequest request, MsgDeleteParam param);
Boolean deleteMsg(MsgDeleteParam param);
/**
* 修改消息体
......@@ -129,6 +130,6 @@ public interface ImMessageService extends BaseService<ImMessage> {
* @param param
* @return
*/
ReaderList getReaders(ActionRequest request, GetReadersParam param);
ReaderList getReaders(GetReadersParam param);
}
package com.wecloud.im.service;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMultiRtcRoomMember;
import io.geekidea.springbootplus.framework.common.service.BaseService;
......@@ -13,10 +12,10 @@ public interface ImMultiRtcRoomMemberService extends BaseService<ImMultiRtcRoomM
/**
* 改变会议成员状态
* @param currentClient
* @param fkClientId
* @param roomId
* @param state
*/
void changeRoomMemberState(ImClient currentClient, String roomId, Integer state);
void changeRoomMemberState(Long fkClientId, String roomId, Integer state);
}
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.dispatch.util.ActionRequestHolder;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
/**
* 请求上下文服务 impl
* @Author luozh
* @Date 2022年04月02日 14:56
* @Version 1.0
*/
@Service
public class ContextServiceImpl implements ContextService {
@Autowired
@Lazy
private ImClientService imClientService;
@Autowired
private ImApplicationService imApplicationService;
@Override
public ImClient getImClientIfNotNullOrThrow() {
ImClient currentClient = imClientService.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
return currentClient;
}
@Override
public ImApplication getImApplicationIfNotNullOrThrow(Long appId) {
ImApplication imApplication = imApplicationService.getCacheById(appId);
if (imApplication == null) {
throw new BusinessException("查无应用信息");
}
return imApplication;
}
}
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -9,20 +21,10 @@ import com.wecloud.im.mapper.ImClientBlacklistMapper;
import com.wecloud.im.param.ImClientBlacklistPageParam;
import com.wecloud.im.param.ImClientBlacklistQueryVo;
import com.wecloud.im.param.add.ImClientBlacklistUpdate;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
* 黑名单 服务实现类
......@@ -40,6 +42,9 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
@Autowired
private ImClientService imClientService;
@Autowired
private ContextService contextService;
@Override
public boolean isBeBlack(String currentClientId, String toClientId) {
ImClientBlacklist one = this.getOne(new QueryWrapper<ImClientBlacklist>().lambda()
......@@ -51,11 +56,8 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
ImClient currentClient = imClientService.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
public Boolean addImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
ImClient beBlacker = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
.eq(ImClient::getClientId, imClientBlacklistUpdate.getClientIdBePrevent()));
......@@ -70,17 +72,14 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
imClientBlacklist.setClientIdBePrevent(beBlacker.getClientId());
this.save(imClientBlacklist);
return ApiResult.ok();
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
public Boolean removeImClientBlacklist(ImClientBlacklistUpdate imClientBlacklistUpdate) {
// 操作者
ImClient currentClient = imClientService.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
// 被拉黑者
ImClient beBlacker = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, currentClient.getFkAppid())
......@@ -92,16 +91,16 @@ public class ImClientBlacklistServiceImpl extends BaseServiceImpl<ImClientBlackl
this.remove(new QueryWrapper<ImClientBlacklist>().lambda()
.eq(ImClientBlacklist::getClientIdPrevent, currentClient.getClientId())
.eq(ImClientBlacklist::getClientIdBePrevent, beBlacker.getClientId()));
return ApiResult.ok();
return true;
}
@Override
public ApiResult<Paging<ImClientBlacklistQueryVo>> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam) {
public Paging<ImClientBlacklistQueryVo> getImClientBlacklistPageList(ImClientBlacklistPageParam imClientBlacklistPageParam) {
Page<ImClientBlacklistQueryVo> page = new PageInfo<>(imClientBlacklistPageParam);
ImClient currentClient = imClientService.getCurrentClient();
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
IPage<ImClientBlacklistQueryVo> imClientBlacklistPageList = imClientBlacklistMapper.getImClientBlacklistPageList(page, currentClient.getClientId());
Paging<ImClientBlacklistQueryVo> imClientBlacklistQueryVoPaging = new Paging<>(imClientBlacklistPageList);
return ApiResult.ok(imClientBlacklistQueryVoPaging);
return imClientBlacklistQueryVoPaging;
}
}
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.dispatch.util.ActionRequestHolder;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImClientDevice;
import com.wecloud.im.enums.FriendStateEnum;
import com.wecloud.im.enums.RelationEnum;
import com.wecloud.im.friend.entity.ImFriend;
import com.wecloud.im.friend.service.ImFriendService;
import com.wecloud.im.mapper.ImClientMapper;
......@@ -25,6 +45,9 @@ import com.wecloud.im.param.add.ImClientHeadPortraitAdd;
import com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate;
import com.wecloud.im.param.add.ImClientNicknameAdd;
import com.wecloud.im.param.add.ImClientNicknameUpdate;
import com.wecloud.im.sdk.enums.FriendStateEnum;
import com.wecloud.im.sdk.enums.RelationEnum;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientDeviceService;
......@@ -33,25 +56,6 @@ import com.wecloud.im.vo.ClientInfoVo;
import com.wecloud.im.vo.GetInfoListVo;
import com.wecloud.im.vo.MyInfoVo;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* 终端表 服务实现类
......@@ -79,13 +83,12 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Autowired
private ImClientDeviceService imClientDeviceService;
@Autowired
private ContextService contextService;
@Override
public MyInfoVo getMyInfo() {
ImClient currentClient = this.getCurrentClient();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
MyInfoVo myInfoVo = new MyInfoVo();
BeanUtils.copyProperties(currentClient, myInfoVo);
return myInfoVo;
......@@ -94,7 +97,7 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateHeadPortrait(ImClientHeadPortraitAdd imClientHeadPortraitAdd) {
ImClient curentClient = getCurrentClient();
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
curentClient.setHeadPortrait(imClientHeadPortraitAdd.getHeadPortrait());
imClientMapper.updateById(curentClient);
......@@ -106,7 +109,7 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
public boolean updateNickname(ImClientNicknameUpdate imClientNicknameUpdate) {
ImClient curentClient = getCurrentClient();
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
curentClient.setNickname(imClientNicknameUpdate.getNickname());
imClientMapper.updateById(curentClient);
......@@ -118,7 +121,7 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
public boolean updateHeadAndNickname(ImClientHeadPortraitAndNicknameUpdate imClientHeadPortraitAndNicknameUpdate) {
ImClient curentClient = getCurrentClient();
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
curentClient.setHeadPortrait(imClientHeadPortraitAndNicknameUpdate.getHeadPortrait());
curentClient.setNickname(imClientHeadPortraitAndNicknameUpdate.getNickname());
imClientMapper.updateById(curentClient);
......@@ -130,8 +133,8 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
}
@Override
public ApiResult<List<GetInfoListVo>> getInfoList(GetClientInfoParam getClientInfoParam) throws Exception {
ImClient curentClient = getCurrentClient();
public List<GetInfoListVo> getInfoList(GetClientInfoParam getClientInfoParam) throws Exception {
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
if (getClientInfoParam.getClientIds() == null || getClientInfoParam.getClientIds().isEmpty()) {
throw new BusinessException("getClientInfoParam.getClientIds() == null");
......@@ -155,12 +158,12 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
List<GetInfoListVo> infoList = imClientMapper.getInfoList(curentClient.getFkAppid(), getClientInfoParam.getConversationId(), getClientInfoParam.getClientIds());
return ApiResult.ok(infoList);
return infoList;
}
@Override
public ClientInfoVo getClientInfo(ClientInfoParam param) {
ImClient currentClient = this.getCurrentClient();
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
if (currentClient == null) {
throw new BusinessException("当前用户登录信息失效");
}
......@@ -192,7 +195,7 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateNickname(ImClientNicknameAdd imClientNicknameAdd) throws Exception {
ImClient curentClient = getCurrentClient();
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
curentClient.setNickname(imClientNicknameAdd.getNickname());
imClientMapper.updateById(curentClient);
......@@ -246,7 +249,7 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
public boolean logout(LogoutParam param) {
ImClient currentClient = getCurrentClient();
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
// 清除设备token
return imClientDeviceService.update(new UpdateWrapper<ImClientDevice>().lambda()
.eq(ImClientDevice::getFkAppid, currentClient.getFkAppid())
......@@ -275,12 +278,19 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
@Override
public ImClient getCurrentClient() {
ImClient imClient = null;
// modify by luozh 2022/04/03 增加是否存在ActionRequest的判断,如果是则说明请求来源于ws 否则是HTTP请求
if (ActionRequestHolder.getActionRequest() != null) {
ActionRequest request = ActionRequestHolder.getActionRequest();
imClient = getCacheImClient(request.getSenderClientId());
} else {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询appid
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
return getCacheImClient(imApplication.getId(), curentJwtToken.getClientId());
imClient = getCacheImClient(imApplication.getId(), curentJwtToken.getClientId());
}
return imClient;
}
@Override
......
......@@ -12,19 +12,9 @@ import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.mapper.ImConversationMembersMapper;
import com.wecloud.im.param.ApiImConversationMembersPageParam;
import com.wecloud.im.param.ApiImConversationMembersQueryVo;
import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.ImConversationMembersPageParam;
import com.wecloud.im.param.ImConversationMembersQueryVo;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.*;
import com.wecloud.im.param.add.ImConversationMemAttrUpdate;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.service.*;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
......@@ -37,15 +27,12 @@ import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -83,6 +70,9 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
@Autowired
private ImConversationMembersMapper imConversationMembersMapper;
@Autowired
private ContextService contextService;
@Override
public ApiResult<List<ApiImConversationMembersQueryVo>> getRestApiImConversationMembersList(ApiImConversationMembersPageParam apiImConversationMembersPageParam, ImApplication imApplication) {
......@@ -162,12 +152,12 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> saveOrUpdateAttr(ImConversationMemAttrUpdate imConversationMemAttrUpdate) {
public Boolean saveOrUpdateAttr(ImConversationMemAttrUpdate imConversationMemAttrUpdate) {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
// 获取当前client
ImClient createClient = contextService.getImClientIfNotNullOrThrow();
// 根据appId查询application
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
ImClient imClientSender = imClientService.getCurrentClient();
......@@ -180,7 +170,7 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
);
if (imConversationMember == null) {
return ApiResult.fail();
return false;
}
......@@ -197,15 +187,8 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
boolean b = imConversationMembersService.updateById(imConversationMember);
if (b) {
//TODO ws下发群成员属性变动事件
return ApiResult.ok();
} else {
return ApiResult.fail();
}
return b;
}
......
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
......@@ -14,9 +39,6 @@ import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.ChatTypeEnum;
import com.wecloud.im.enums.GroupRoleEnum;
import com.wecloud.im.enums.MutedEnum;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ImClientSimpleDto;
......@@ -34,6 +56,10 @@ import com.wecloud.im.param.add.ImConversationAttrUpdate;
import com.wecloud.im.param.add.ImConversationCreate;
import com.wecloud.im.param.add.ImConversationDisplayUpdate;
import com.wecloud.im.param.add.ImConversationNameUpdate;
import com.wecloud.im.sdk.enums.ChatTypeEnum;
import com.wecloud.im.sdk.enums.GroupRoleEnum;
import com.wecloud.im.sdk.enums.MutedEnum;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
......@@ -49,29 +75,6 @@ import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.utils.JsonUtils;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 会话表 服务实现类
......@@ -105,6 +108,9 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Autowired
private ImMessageService imMessageService;
@Autowired
private ContextService contextService;
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveImConversation(ImConversation imConversation) {
......@@ -113,15 +119,15 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<ImConversationCreateVo> createImConversation(ImConversationCreate imConversationCreate) {
ImClient createClient = imClientService.getCurrentClient();
public ImConversationCreateVo createImConversation(ImConversationCreate imConversationCreate) {
ImClient createClient = contextService.getImClientIfNotNullOrThrow();
if (CollectionUtils.isEmpty(imConversationCreate.getClientIds())) {
log.info("未找到群成员信息");
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, null);
throw new BusinessException(ApiCode.PARAMETER_EXCEPTION);
}
if (BaseEnum.valueOf(ChatTypeEnum.class, imConversationCreate.getChatType()) == null) {
log.info("会话类型不存在");
return ApiResult.result(ApiCode.PARAMETER_EXCEPTION, null);
throw new BusinessException(ApiCode.PARAMETER_EXCEPTION);
}
// 成员不存在,不能创建会话
for (String clientId : imConversationCreate.getClientIds()) {
......@@ -131,14 +137,12 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
.eq(ImClient::getClientId, clientId));
if (imClient == null) {
log.info("成员不存在,不能创建会话 clientId:{}", clientId);
return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
throw new BusinessException(ApiCode.CLIENT_NOT_FOUNT);
}
}
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
// 该应用 是否允许创建重复单聊类型会话 0不允许 1允许
if (imApplication.getRepeatSessionStatus() != null && imApplication.getRepeatSessionStatus() == 0) {
......@@ -156,7 +160,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 返回已存在的单聊类型会话id
ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
imConversationCreateVo.setId(repetitionConversationInfo.getId());
return ApiResult.ok(imConversationCreateVo);
return imConversationCreateVo;
}
}
} else {
......@@ -179,7 +183,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
imConversationCreateVo.setId(repetitionConversation);
// 为重复
return ApiResult.ok(imConversationCreateVo);
return imConversationCreateVo;
}
}
}
......@@ -261,17 +265,17 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
imConversationCreateVo.setId(imConversationId);
return ApiResult.ok(imConversationCreateVo);
return imConversationCreateVo;
}
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> addClientToConversation(ImClientToConversation imClientToConversation) {
public Boolean addClientToConversation(ImClientToConversation imClientToConversation) {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
// 获取当前client
ImClient createClient = contextService.getImClientIfNotNullOrThrow();
// 根据appId查询application
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
ImClient imClientSender = imClientService.getCurrentClient();
......@@ -285,7 +289,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
return ApiResult.fail();
throw new BusinessException("没有成员");
}
int needAddCount = 0;
......@@ -296,7 +300,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getClientId, id));
if (clientToConversation == null) {
return ApiResult.fail(ApiCode.CLIENT_NOT_FOUNT, null);
throw new BusinessException(ApiCode.CLIENT_NOT_FOUNT);
}
// 判断用户是否已经在该会话
ImConversationMembers members = imConversationMembersService.getOne(new QueryWrapper<ImConversationMembers>().lambda()
......@@ -366,7 +370,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
imConversationMapper.upgradeToThousandChat(imApplication.getId(), imClientToConversation.getConversationId());
}
return ApiResult.ok();
return true;
}
......@@ -404,11 +408,11 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> delClientToConversation(ImClientToConversation imClientToConversation) throws Exception {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
public Boolean delClientToConversation(ImClientToConversation imClientToConversation) throws Exception {
// 获取当前client
ImClient createClient = contextService.getImClientIfNotNullOrThrow();
// 根据appId查询application
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
ImClient imClientSender = imClientService.getCurrentClient();
// 判断是否为群主
ImConversationMembers conversationMember = imConversationMembersService.getOne(
......@@ -417,7 +421,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
.eq(ImConversationMembers::getFkClientId, imClientSender.getId())
);
if (conversationMember == null || !GroupRoleEnum.OWNER.getCode().equals(conversationMember.getRole())) {
return ApiResult.result(false);
return false;
}
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
......@@ -428,7 +432,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
return ApiResult.fail();
throw new BusinessException("没有成员");
}
int needAddCount = 0;
......@@ -508,12 +512,13 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 将群成员数量减
imConversationMapper.addMemberCount(imApplication.getId(), imClientToConversation.getConversationId(), needAddCount);
return ApiResult.ok();
return true;
}
@Override
public void disband(DisbandConversationParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
// 判断是否为群主
ImConversationMembers conversationMember = imConversationMembersService.getOne(
new QueryWrapper<ImConversationMembers>().lambda()
......@@ -591,8 +596,9 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation) {
ImClient currentClient = imClientService.getCurrentClient();
public Boolean leaveConversation(ImClientLeaveConversation imClientToConversation) {
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
ImConversation imConversation = imConversationService.getById(imClientToConversation.getConversationId());
if (imConversation == null) {
......@@ -691,7 +697,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// 群主转移给下一个人
imConversationMembersService.updateById(conversationMember);
}
return ApiResult.ok();
return true;
}
......@@ -704,10 +710,10 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean transferOwner(TransferOwnerParam param) {
// shiro线程中获取当前token
JwtToken curentJwtToken = JwtUtil.getCurrentJwtToken();
// 根据appKey查询application
ImApplication imApplication = imApplicationService.getCacheAppByAppKey(curentJwtToken.getAppKey());
// 获取当前client
ImClient createClient = contextService.getImClientIfNotNullOrThrow();
// 根据appId查询application
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
ImClient imClientSender = imClientService.getCurrentClient();
// 判断操作人是否为群主
......@@ -742,7 +748,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
*/
@Override
public Boolean setAdmins(SetAdminsParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
// 判断操作人是否为群主
ImConversationMembers currentMember = imConversationMembersService.getOne(
new QueryWrapper<ImConversationMembers>().lambda()
......@@ -758,7 +765,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
}
List<Long> fkClientIds = simpleClients.stream()
.filter(s -> !currentMember.getId().equals(s.getId()))
.map(s -> s.getId()).collect(Collectors.toList());
.map(ImClientSimpleDto::getId).collect(Collectors.toList());
imConversationMembersService.setAdminsForConversation(param, fkClientIds);
return true;
}
......@@ -771,7 +778,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
*/
@Override
public Boolean mutedGroup(MutedGroupParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
// 当前操作人不属于群主或管理人员
......@@ -855,7 +863,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
public Boolean mutedGroupMember(MutedGroupMemberParam param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
// 当前操作人不属于群主或管理人员
......@@ -906,7 +915,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate param) {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
ImConversation imConversationById = imConversationService.getById(param.getConversationId());
if (!this.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
......@@ -1059,7 +1069,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateDisplayConversation(ImConversationDisplayUpdate imConversationDisplayUpdate) {
ImClient curentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
for (Long id : imConversationDisplayUpdate.getConversationIds()) {
// 修改为删除隐藏状态
boolean update = imConversationMembersService.update(new UpdateWrapper<ImConversationMembers>()
......@@ -1093,7 +1104,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
public List<ConversationVo> getMyImConversationListAndMsgCount() {
try {
ImClient currentClient = imClientService.getCurrentClient();
// 获取当前client
ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> myImConversationListAndMsgCount = imConversationMapper.getMyImConversationListAndMsgCount(currentClient.getId(), currentClient.getClientId(), null);
......@@ -1114,6 +1126,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
myImConversationListAndMsgCountNew.add(myconversationlistvo);
}
log.info("{} 查询加入的会话列表结果 {}", currentClient.getClientId(), JSON.toJSONString(myImConversationListAndMsgCountNew));
return myImConversationListAndMsgCountNew;
} catch (Exception e) {
log.info("查询所有会话异常 ", e);
......@@ -1125,7 +1138,8 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
@Override
public ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param) {
try {
ImClient client = imClientService.getCurrentClient();
// 获取当前client
ImClient client = contextService.getImClientIfNotNullOrThrow();
// 查询用户加入的所有会话 与每个会话的未读条数 成员
List<ConversationVo> conversationList = imConversationMapper.getMyImConversationListAndMsgCount(client.getId(), client.getClientId(), param.getId());
if (CollectionUtils.isEmpty(conversationList)) {
......
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Maps;
import com.wecloud.im.entity.ImApplication;
......@@ -8,11 +24,11 @@ import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.ReadMsgStatusEnum;
import com.wecloud.im.mapper.ImInboxMapper;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.param.MsgReadStatusUpdateParam;
import com.wecloud.im.param.UpdateMsgReadStatusByConversationParam;
import com.wecloud.im.sdk.enums.ReadMsgStatusEnum;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
......@@ -22,20 +38,6 @@ import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
/**
* 消息收件箱表 服务实现类
......@@ -96,7 +98,7 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> updateImMsgReceived(ImMsgReceivedStatusUpdate imMsgReceivedUpdate) {
public Boolean updateImMsgReceived(ImMsgReceivedStatusUpdate imMsgReceivedUpdate) {
ImClient curentClient = imClientService.getCurrentClient();
// 修改已接收状态
......@@ -119,7 +121,7 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
this.updateImMsgRead(msgReadStatusUpdateParam);
}
return ApiResult.ok();
return true;
}
/**
......@@ -137,7 +139,7 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> updateImMsgRead(MsgReadStatusUpdateParam msgReadStatusUpdateParam) {
public Boolean updateImMsgRead(MsgReadStatusUpdateParam msgReadStatusUpdateParam) {
ImClient curentClient = imClientService.getCurrentClient();
// 修改已读状态
......@@ -151,7 +153,7 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
contentMap.put("receiverId", curentClient.getClientId());
sendMsgStatus(curentClient, MsgTypeEnum.CLIENT_READ_MSG, contentMap, msgReadStatusUpdateParam.getMsgIds());
return ApiResult.ok();
return true;
}
......@@ -176,7 +178,7 @@ public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox>
HashMap<String, String> contentMap = Maps.newHashMap();
contentMap.put("receiverId", currentClient.getClientId());
sendMsgStatus(currentClient, MsgTypeEnum.CLIENT_READ_MSG, contentMap, msgIds);
return null;
return true;
}
/**
......
package com.wecloud.im.service.impl;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.wecloud.dispatch.extend.ActionRequest;
import com.wecloud.im.entity.ImApiMessageOnlineSend;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
......@@ -14,7 +32,6 @@ import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.enums.ChatTypeEnum;
import com.wecloud.im.mapper.ImMessageMapper;
import com.wecloud.im.mq.MqSender;
import com.wecloud.im.param.ChatContentVo;
......@@ -25,6 +42,8 @@ import com.wecloud.im.param.MsgDeleteParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.sdk.enums.ChatTypeEnum;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
......@@ -44,23 +63,7 @@ import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.pushserver.client.model.constant.MqConstant;
import com.wecloud.pushserver.client.model.dto.PushDTO;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.Date;
import java.util.List;
import java.util.Map;
/**
* 消息存储表 服务实现类
......@@ -89,6 +92,9 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
private ImConversationMembersService imConversationMembersService;
@Autowired
private ContextService contextService;
@Autowired
private ChannelSender channelSender;
@Autowired
......@@ -202,23 +208,9 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean withdrawMsg(ActionRequest request, ImMsgRecall imMsgRecall) {
ImClient imClientSender;
ImApplication imApplication;
if (request != null) {
imClientSender = imClientService.getCacheImClient(request.getSenderClientId());
imApplication = imApplicationService.getCacheById(imClientSender.getFkAppid());
} else {
imClientSender = imClientService.getCurrentClient();
// 查询imApplication
imApplication = imApplicationService.getCacheById(imClientSender.getFkAppid());
}
if (imClientSender == null) {
throw new BusinessException("查无发送用户信息");
}
if (imApplication == null) {
throw new BusinessException("查无应用信息");
}
public Boolean withdrawMsg(ImMsgRecall imMsgRecall) {
ImClient imClientSender = contextService.getImClientIfNotNullOrThrow();
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(imClientSender.getFkAppid());
ImMessage messageById = this.getById(imMsgRecall.getMsgId());
// 判断该消息是否是该客户端发送 todo 单向撤回、双向撤回开关可配置
......@@ -313,23 +305,9 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
}
@Override
public Boolean deleteMsg(ActionRequest request, MsgDeleteParam param) {
ImClient imClientSender;
ImApplication imApplication;
if (request != null) {
imClientSender = imClientService.getCacheImClient(request.getSenderClientId());
imApplication = imApplicationService.getCacheById(imClientSender.getFkAppid());
} else {
imClientSender = imClientService.getCurrentClient();
// 查询imApplication
imApplication = imApplicationService.getCacheById(imClientSender.getFkAppid());
}
if (imClientSender == null) {
throw new BusinessException("查无发送用户信息");
}
if (imApplication == null) {
throw new BusinessException("查无应用信息");
}
public Boolean deleteMsg(MsgDeleteParam param) {
ImClient imClientSender = contextService.getImClientIfNotNullOrThrow();
ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(imClientSender.getFkAppid());
// todo 单向撤回、双向撤回开关可配置
Boolean deleteOther = true;
List<ImMessage> imMessageList = this.listByIds(param.getMsgIds());
......@@ -457,16 +435,8 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
* @return
*/
@Override
public ReaderList getReaders(ActionRequest request, GetReadersParam param) {
ImClient imClientSender;
if (request != null) {
imClientSender = imClientService.getCacheImClient(request.getSenderClientId());
} else {
imClientSender = imClientService.getCurrentClient();
}
if (imClientSender == null) {
throw new BusinessException("查无发送用户信息");
}
public ReaderList getReaders(GetReadersParam param) {
ImClient imClientSender = contextService.getImClientIfNotNullOrThrow();
List<ReaderVo> readerVos = imMessageMapper.getReaders(imClientSender.getId(), param);
if (CollectionUtils.isEmpty(readerVos)) {
return null;
......
package com.wecloud.im.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMultiRtcRoomMember;
import com.wecloud.im.mapper.ImMultiRtcRoomMemberMapper;
import com.wecloud.im.service.ImMultiRtcRoomMemberService;
......@@ -10,6 +9,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
* @Author wenzhida
* @Date 2022/3/16 9:27
......@@ -23,10 +24,11 @@ public class ImMultiRtcRoomMemberServiceImpl extends BaseServiceImpl<ImMultiRtcR
private ImMultiRtcRoomMemberMapper imMultiRtcRoomMemberMapper;
@Override
public void changeRoomMemberState(ImClient currentClient, String roomId, Integer state) {
public void changeRoomMemberState(Long fkClientId, String roomId, Integer state) {
this.update(new UpdateWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, roomId)
.eq(ImMultiRtcRoomMember::getFkClientId, currentClient.getId())
.eq(ImMultiRtcRoomMember::getFkClientId, fkClientId)
.set(ImMultiRtcRoomMember::getHeartbeatTime, new Date())
.set(ImMultiRtcRoomMember::getState, state));
}
}
package com.wecloud.im.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.wecloud.im.entity.ImMultiRtcRoom;
import com.wecloud.im.enums.MultiRtcRoomStateEnum;
import com.wecloud.im.mapper.ImMultiRtcRoomMapper;
import com.wecloud.im.service.ImMultiRtcRoomService;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.wecloud.im.entity.ImMultiRtcRoom;
import com.wecloud.im.mapper.ImMultiRtcRoomMapper;
import com.wecloud.im.service.ImMultiRtcRoomService;
/**
* @Author wenzhida
* @Date 2022/3/16 9:27
......@@ -28,7 +28,7 @@ public class ImMultiRtcRoomServiceImpl extends BaseServiceImpl<ImMultiRtcRoomMap
private ImMultiRtcRoomService imMultiRtcRoomService;
@Override
@Cacheable(key = "'rtcRoomKey_' + #p0+#p1")
// @Cacheable(key = "'rtcRoomKey_' + #p0+#p1")
public ImMultiRtcRoom getCachedMultiRtcRoom(Long fkAppid, String roomId) {
ImMultiRtcRoom rtcRoom = imMultiRtcRoomService.getOne(new QueryWrapper<ImMultiRtcRoom>().lambda()
.eq(ImMultiRtcRoom::getFkAppid, fkAppid)
......
......@@ -20,6 +20,8 @@ import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.thousandchat.cache.ThousandChatCacheManager;
import com.wecloud.im.thousandchat.param.LastestReceivedMsg;
import com.wecloud.im.thousandchat.service.ThousandChatService;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
......@@ -31,9 +33,16 @@ import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
......@@ -46,7 +55,8 @@ import java.util.Map;
*/
@Slf4j
@Component
@ActionMapping(value = "/chat")
@ActionMapping
@Api(value = "万人群消息处理", tags = {"万人群消息处理"})
public class ThousandChatAction {
@Autowired
......@@ -63,11 +73,14 @@ public class ThousandChatAction {
private ChannelSender channelSender;
@Autowired
private ThousandChatCacheManager thousandChatCacheManager;
@Autowired
private ThousandChatService thousandChatService;
@Autowired
private MqSender mqSender;
@ActionMapping("/thousand/send")
@ActionMapping("/chat/thousand/send")
@ApiOperation(value = "万人群消息发送")
public void sendMsg(ActionRequest request, ChatContentVo data, String reqId) {
if (log.isDebugEnabled()) {
log.debug("接收到参数,reqId: {},\n data: {}, ", data);
......@@ -132,6 +145,24 @@ public class ThousandChatAction {
}
/**
* 消息修改为已接收状态
*/
@ActionMapping("/imState/msgReceivedUpdate")
@ApiOperation(value = "万人群消息修改为已接收状态")
public ApiResult<Boolean> updateImMsgReceived(@RequestBody @Validated LastestReceivedMsg lastestReceivedMsg) {
return thousandChatService.updateImMsgReceived(lastestReceivedMsg);
}
/**
* 消息修改为已读状态
*/
@ActionMapping("/imState/msgReadUpdate")
@ApiOperation(value = "万人群消息修改为已读状态")
public ApiResult<Boolean> updateInMsgReadUpdate(Long lastestMsgId) {
return thousandChatService.updateImMsgRead(lastestMsgId);
}
/**
* 发送消息给在线客户
* @param data
* @param imMessageOnlineSend
......
......@@ -20,29 +20,11 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/imState")
@Api(value = "万人群消息处理API", tags = {"万人群消息处理"})
@Api(value = "万人群消息处理API", tags = {"万人群消息处理API"})
public class ThousandChatController extends BaseController {
@Autowired
private ThousandChatService thousandChatService;
/**
* 消息修改为已接收状态
*/
@PostMapping("/msgReceivedUpdate")
@ApiOperation(value = "万人群消息修改为已接收状态")
public ApiResult<Boolean> updateImMsgReceived(@RequestBody @Validated LastestReceivedMsg lastestReceivedMsg) {
return thousandChatService.updateImMsgReceived(lastestReceivedMsg);
}
/**
* 消息修改为已读状态
*/
@PostMapping("/msgReadUpdate")
@ApiOperation(value = "万人群消息修改为已读状态")
public ApiResult<Boolean> updateInMsgReadUpdate(Long lastestMsgId) {
return thousandChatService.updateImMsgRead(lastestMsgId);
}
}
package com.wecloud.im.thousandchat.param;
import com.wecloud.dispatch.common.BaseRequest;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -9,6 +10,7 @@ import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author lixiaozhong
......@@ -16,9 +18,8 @@ import javax.validation.constraints.NotNull;
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "ImMsgReceivedStatusUpdate")
public class LastestReceivedMsg extends BaseEntity {
@ApiModel(value = "LastestReceivedMsg")
public class LastestReceivedMsg implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "消息id,只需要发送最新的一条已接收消息", required = true)
......
......@@ -42,7 +42,7 @@ public class ClientInfoVo implements Serializable {
/**
* 与我关系
* @see com.wecloud.im.enums.RelationEnum
* @see com.wecloud.im.sdk.enums.RelationEnum
*/
@ApiModelProperty("与我关系 1-陌生人 2-好友 3-被我拉黑")
private Integer relation;
......
......@@ -37,14 +37,14 @@ public class ConversationMemberVo implements Serializable {
/**
* 群内角色
* @see com.wecloud.im.enums.GroupRoleEnum
* @see com.wecloud.im.sdk.enums.GroupRoleEnum
*/
@ApiModelProperty("群内角色")
private Integer role;
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
package com.wecloud.im.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
......@@ -10,6 +9,8 @@ import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* <pre>
* 会话表 查询结果对象
......@@ -22,7 +23,8 @@ import java.util.HashMap;
@Accessors(chain = true)
@ApiModel(value = "MyConversationListVo")
public class ConversationVo implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = -4330507756623541941L;
@ApiModelProperty("会话id")
private Long id;
......@@ -66,7 +68,7 @@ public class ConversationVo implements Serializable {
/**
* 禁言开关
* @see com.wecloud.im.enums.MutedEnum
* @see com.wecloud.im.sdk.enums.MutedEnum
*/
@ApiModelProperty("禁言开关 1-未禁言 2-禁言")
private Integer muted;
......
......@@ -14,7 +14,7 @@ public enum WsResponseCmdEnum {
/**
* 服务端下发通知型消息,例如:好友申请,好友认证结果.
* 参数值参考{@link com.wecloud.im.enums.EventResponseSubCmdEnum EventResponseSubCmdEnum}
* 参数值参考{@link com.wecloud.im.sdk.enums.EventResponseSubCmdEnum EventResponseSubCmdEnum}
*/
NOTICE_EVENT_MSG(7),
......
package com.wecloud.im.ws.manager;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.ws.cache.UserStateListener;
import com.wecloud.im.ws.model.ClientInfo;
import com.wecloud.im.ws.utils.RedisUtils;
......
package com.wecloud.im.ws.model;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.config.il8n.I18nMessageUtil;
import io.geekidea.springbootplus.framework.config.il8n.LanguageEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import com.wecloud.dispatch.util.ActionRequestHolder;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
/**
* @Description websocket服务端响应消息和下方消息的封装对象
......@@ -41,4 +50,57 @@ public class WsResponse<T> implements Serializable {
*/
private String reqId;
public static WsResponse<Boolean> result(ApiCode apiCode) {
return result(apiCode, true);
}
public static <T> WsResponse<T> result(ApiCode apiCode, T data) {
return result(apiCode, "", data);
}
public static <T> WsResponse<T> result(ApiCode apiCode, String message, T data) {
return result(WsResponseCmdEnum.RES.getCmdCode(), apiCode, message, data);
}
public static <T> WsResponse<T> result(Integer cmd, ApiCode apiCode, String message, T data) {
String success = "SUCCESS";
try {
message = I18nMessageUtil.getMessage(LanguageEnum.getLanguageType(null), apiCode.getMessage(), success);
} catch (IOException e) {
message = success;
}
WsResponse<T> response = new WsResponse<>();
response.setCmd(cmd).setCode(apiCode.getCode()).setMsg(message).setData(data);
if (ActionRequestHolder.getActionRequest() != null) {
response.setReqId(ActionRequestHolder.getReqId());
}
return response;
}
public static WsResponse<Map<String, Boolean>> ok() {
return ok(Collections.emptyMap());
}
public static <T> WsResponse<T> ok(T data) {
return result(ApiCode.SUCCESS, data);
}
public static WsResponse<Map<String, Boolean>> fail() {
return ok(Collections.emptyMap());
}
public static WsResponse<Boolean> fail(String message) {
return result(ApiCode.FAIL, message, false);
}
public static <T> WsResponse<T> fail(ApiCode apiCode) {
return result(apiCode, "", null);
}
public static <T> WsResponse<T> fail(ApiCode apiCode, String message) {
return result(apiCode, message, null);
}
}
......@@ -43,7 +43,7 @@ public class ChannelSender {
* 指定ip调用,router=address;
* injvm = false要设置成false,否则会调用到本地提供者
*/
@DubboReference(injvm = false, interfaceClass = RouterSendService.class, parameters = {"router", "address"})
@DubboReference(injvm = false, check = false, interfaceClass = RouterSendService.class, parameters = {"router", "address"})
private RouterSendService routerSendService;
/**
......@@ -128,15 +128,21 @@ public class ChannelSender {
String msgJson = JsonUtils.encodeJson(responseModel);
List<ClientChannelInfo> channelInfos = userStateCacheManager.findOnlineInfosByClientId(toClientId);
log.info("获取在线用户入参 {}, 结果 {}", toClientId, JSON.toJSONString(channelInfos));
// 一个用户存在多端的情况,所以先进行分类,key是ip地址,value是channel的列表
Map<String, List<ClientChannelInfo>> ipChannels = channelInfos.stream().collect(Collectors.groupingBy(ClientChannelInfo::getLanIp));
log.info("分组在线用户入参 {}, 结果 {}", toClientId, JSON.toJSONString(ipChannels));
for (Map.Entry<String, List<ClientChannelInfo>> channelInfoEntry : ipChannels.entrySet()) {
log.info("在线用户入参 {}, 具体ip结果 {}", toClientId, JSON.toJSONString(channelInfoEntry));
// 是否为当前机器的ip
if (GetIpUtils.getlanIp().equals(channelInfoEntry.getKey())) {
// 调用本地下发
log.info("在线用户入参 {}, 具体ip结果 {}", toClientId, JSON.toJSONString(channelInfoEntry));
for(ClientChannelInfo clientChannelInfo : channelInfoEntry.getValue()) {
this.sendMsgLocal(toClientId, clientChannelInfo.getPlatform(), msgJson);
}
......@@ -217,8 +223,10 @@ public class ChannelSender {
* @return
*/
private boolean sendMsgLocal(String key, String msgJsonStr) {
log.info("消息推送 key {} 内容 {}", key, msgJsonStr);
ClientInfo clientInfo = ChannelManager.SESSION_INFO_MAP.get(key);
if (clientInfo == null) {
log.info("消息推送 key {} 本地map取设备信息为空", key);
return false;
}
......@@ -229,7 +237,7 @@ public class ChannelSender {
}
// 判断连接是否断开
if (nioSocketChannel.isShutdown()) {
log.warn("writeData 已连接断开: {}\n channelId: {}", msgJsonStr, nioSocketChannel.id().asLongText());
log.info("writeData 已连接断开: {}\n channelId: {}", msgJsonStr, nioSocketChannel.id().asLongText());
return false;
}
......
package com.wecloud.multimeet.entity.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
......@@ -27,7 +26,7 @@ public class RoomMemberDto implements Serializable {
/**
* 多人音视频房间成员状态枚举
* @see com.wecloud.im.enums.MultiRtcMemberStateEnum
* @see com.wecloud.im.sdk.enums.MultiRtcMemberStateEnum
*/
private Integer state;
......
package com.wecloud.multimeet.service;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
/**
......@@ -37,4 +39,26 @@ public interface MultiMeetService {
*/
void leave(LeaveFromMultiMeetParam param);
/**
* 拒绝接听
* @param param
*/
void notAnswered(NotAnsweredMultiMeetParam param);
/**
* 心跳接收
* @param param
*/
void heartbeat(HeartbeatMultiMeetParam param);
/**
* 呼叫超时逻辑处理
*/
void callingTimeout();
/**
* 异常断线逻辑处理
*/
void disconnect();
}
package com.wecloud.multimeet.service.impl;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMultiRtcRoom;
import com.wecloud.im.entity.ImMultiRtcRoomMember;
import com.wecloud.im.enums.MultiRtcMemberStateEnum;
import com.wecloud.im.enums.MultiRtcRoomStateEnum;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.im.sdk.enums.MultiRtcMemberStateEnum;
import com.wecloud.im.sdk.enums.MultiRtcRoomStateEnum;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImMultiRtcRoomMemberService;
import com.wecloud.im.service.ImMultiRtcRoomService;
......@@ -24,14 +39,6 @@ import com.wecloud.multimeet.entity.response.MultiMeetRejectResponse;
import com.wecloud.multimeet.service.MultiMeetService;
import com.wecloud.multimeet.service.WsMultiMeetWrite;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @Author wenzhida
......@@ -100,36 +107,59 @@ public class MultiMeetServiceImpl implements MultiMeetService {
continue;
}
// 占线 通知邀请方
ImMultiRtcRoomMember rtcRoomMember = imMultiRtcRoomMemberService.getOne(new QueryWrapper<ImMultiRtcRoomMember>().lambda()
List<ImMultiRtcRoomMember> busyMember = imMultiRtcRoomMemberService.list(new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getClientId, toClientId)
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId()));
if (rtcRoomMember != null && MultiRtcMemberStateEnum.ANSWERED.getCode().equals(rtcRoomMember.getState())) {
.in(ImMultiRtcRoomMember::getState, Lists.newArrayList(MultiRtcMemberStateEnum.ANSWERED.getCode(), MultiRtcMemberStateEnum.CALLING.getCode())));
if (CollectionUtils.isNotEmpty(busyMember)) {
MultiMeetBusyResponse multiMeetBusyResponse = new MultiMeetBusyResponse();
multiMeetBusyResponse.setConversationId(param.getConversationId());
multiMeetBusyResponse.setRoomId(param.getRoomId());
multiMeetBusyResponse.setClientId(currentClient.getClientId());
multiMeetBusyResponse.setBusyClientId(rtcRoomMember.getClientId());
multiMeetBusyResponse.setBusyClientId(busyMember.get(0).getClientId());
multiMeetBusyResponse.setTimestamp(System.currentTimeMillis());
wsMultiMeetWrite.busy(multiMeetBusyResponse, rtcRoomMember.getFkClientId());
wsMultiMeetWrite.busy(multiMeetBusyResponse, currentClient.getId());
continue;
}
ImMultiRtcRoomMember rtcRoomMember = imMultiRtcRoomMemberService.getOne(new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getClientId, toClientId)
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId()));
if (rtcRoomMember != null) {
// 该房间已邀请过一次,再次发起邀请
rtcRoomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode());
rtcRoomMember.setCallTime(new Date());
imMultiRtcRoomMemberService.updateById(rtcRoomMember);
continue;
}
ImMultiRtcRoomMember roomMember = new ImMultiRtcRoomMember();
roomMember.setId(SnowflakeUtil.getId());
roomMember.setFkRtcRoomId(rtcRoom.getId());
roomMember.setRoomId(param.getRoomId());
roomMember.setFkClientId(toClient.getId());
roomMember.setClientId(toClient.getClientId());
roomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode());
roomMember.setCallTime(new Date());
roomMember.setCreateTime(new Date());
roomMember.setUpdateTime(new Date());
roomMembersToSave.add(roomMember);
RoomMemberDto roomMemberDto = new RoomMemberDto();
roomMemberDto.setFkClientId(toClient.getId());
roomMemberDto.setClientId(toClient.getClientId());
roomMemberDto.setState(MultiRtcMemberStateEnum.CALLING.getCode());
members.add(roomMemberDto);
}
// 将邀请人存入房间成员
ImMultiRtcRoomMember roomMember = new ImMultiRtcRoomMember();
roomMember.setId(SnowflakeUtil.getId());
roomMember.setFkRtcRoomId(rtcRoom.getId());
roomMember.setRoomId(param.getRoomId());
roomMember.setFkClientId(currentClient.getId());
roomMember.setClientId(currentClient.getClientId());
roomMember.setState(MultiRtcMemberStateEnum.ANSWERED.getCode());
roomMember.setCallTime(new Date());
roomMember.setHeartbeatTime(new Date());
roomMember.setCreateTime(new Date());
roomMember.setUpdateTime(new Date());
roomMembersToSave.add(roomMember);
imMultiRtcRoomMemberService.saveBatch(roomMembersToSave);
for (RoomMemberDto member : members) {
// ws向接收方发送通知
......@@ -148,10 +178,11 @@ public class MultiMeetServiceImpl implements MultiMeetService {
@Override
public void reject(RejectToMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient, param.getRoomId(), MultiRtcMemberStateEnum.REJECTED.getCode());
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient.getId(), param.getRoomId(), MultiRtcMemberStateEnum.REJECTED.getCode());
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId())
.in(ImMultiRtcRoomMember::getState, Lists.newArrayList(MultiRtcMemberStateEnum.ANSWERED.getCode(), MultiRtcMemberStateEnum.CALLING.getCode()))
.ne(ImMultiRtcRoomMember::getClientId, currentClient.getClientId())
);
for (ImMultiRtcRoomMember imMultiRtcRoomMember : rtcRoomMemberList) {
......@@ -184,10 +215,11 @@ public class MultiMeetServiceImpl implements MultiMeetService {
imMultiRtcRoomService.deleteMultiRtcRoomCache(currentClient.getFkAppid(), param.getRoomId());
imMultiRtcRoomService.updateMultiRtcRoomState(param.getRoomId(), MultiRtcRoomStateEnum.MEETING.getCode());
}
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient, param.getRoomId(), MultiRtcMemberStateEnum.ANSWERED.getCode());
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient.getId(), param.getRoomId(), MultiRtcMemberStateEnum.ANSWERED.getCode());
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId())
.in(ImMultiRtcRoomMember::getState, Lists.newArrayList(MultiRtcMemberStateEnum.ANSWERED.getCode(), MultiRtcMemberStateEnum.CALLING.getCode()))
.ne(ImMultiRtcRoomMember::getClientId, currentClient.getClientId())
);
for (ImMultiRtcRoomMember imMultiRtcRoomMember : rtcRoomMemberList) {
......@@ -211,10 +243,11 @@ public class MultiMeetServiceImpl implements MultiMeetService {
@Override
public void leave(LeaveFromMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient, param.getRoomId(), MultiRtcMemberStateEnum.LEAVE.getCode());
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient.getId(), param.getRoomId(), MultiRtcMemberStateEnum.LEAVE.getCode());
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId())
.in(ImMultiRtcRoomMember::getState, Lists.newArrayList(MultiRtcMemberStateEnum.ANSWERED.getCode(), MultiRtcMemberStateEnum.CALLING.getCode()))
.ne(ImMultiRtcRoomMember::getClientId, currentClient.getClientId())
);
for (ImMultiRtcRoomMember imMultiRtcRoomMember : rtcRoomMemberList) {
......@@ -234,4 +267,57 @@ public class MultiMeetServiceImpl implements MultiMeetService {
}
}
@Override
public void notAnswered(NotAnsweredMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
imMultiRtcRoomMemberService.changeRoomMemberState(currentClient.getId(), param.getRoomId(), MultiRtcMemberStateEnum.NOT_ANSWERED.getCode());
}
@Override
public void heartbeat(HeartbeatMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
imMultiRtcRoomMemberService.update(new UpdateWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId())
.eq(ImMultiRtcRoomMember::getFkClientId, currentClient.getId())
.set(ImMultiRtcRoomMember::getHeartbeatTime, new Date()));
}
@Override
public void callingTimeout() {
// 60 秒之前的时间
Date beforeTime = DateUtils.addSeconds(new Date(), -60);
// 获取呼叫时间为120秒之前 并且状态为呼叫中的会议成员
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.lt(ImMultiRtcRoomMember::getCallTime, beforeTime)
.eq(ImMultiRtcRoomMember::getState, MultiRtcMemberStateEnum.CALLING.getCode())
);
if (CollectionUtils.isEmpty(rtcRoomMemberList)) {
return;
}
for (ImMultiRtcRoomMember roomMember : rtcRoomMemberList) {
roomMember.setState(MultiRtcMemberStateEnum.NOT_ANSWERED.getCode());
}
imMultiRtcRoomMemberService.updateBatchById(rtcRoomMemberList);
}
@Override
public void disconnect() {
// 20 秒之前的时间
Date beforeTime = DateUtils.addSeconds(new Date(), -20);
// 获取最后心跳时间为20秒之前 并且状态为接听中的会议成员
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.lt(ImMultiRtcRoomMember::getHeartbeatTime, beforeTime)
.eq(ImMultiRtcRoomMember::getState, MultiRtcMemberStateEnum.ANSWERED.getCode())
);
if (CollectionUtils.isEmpty(rtcRoomMemberList)) {
return;
}
for (ImMultiRtcRoomMember roomMember : rtcRoomMemberList) {
roomMember.setState(MultiRtcMemberStateEnum.DISCONNECT.getCode());
}
imMultiRtcRoomMemberService.updateBatchById(rtcRoomMemberList);
}
}
......@@ -11,7 +11,7 @@ public class RtcCallResponse extends RtcDataBase implements Serializable {
/**
* 类型: "video" 或 "voice"
* @see com.wecloud.im.enums.CallTypeEnum
* @see com.wecloud.im.sdk.enums.CallTypeEnum
*/
private Integer callType;
......
package com.wecloud.rtc.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import com.wecloud.im.param.rtc.*;
/**
* 管理rtc频道
......@@ -18,22 +10,22 @@ public interface RtcService {
/**
* 创建一个频道,并向接收方发送系统推送
*/
ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam);
CreateRtcChannelResult createAndCall(CreateRtcChannelParam createRtcChannelParam);
/**
* 加入频道
*/
ApiResult<Boolean> join(JoinRtcChannelParam joinRtcChannelParam);
Boolean join(JoinRtcChannelParam joinRtcChannelParam);
/**
* 拒接加入频道
*/
ApiResult<Boolean> reject(RejectRtcChannelParam rejectRtcChannelParam);
Boolean reject(RejectRtcChannelParam rejectRtcChannelParam);
/**
* 退出频道
*/
ApiResult<Boolean> leave(LeaveRtcChannelParam leaveRtcChannelParam);
Boolean leave(LeaveRtcChannelParam leaveRtcChannelParam);
/**
* SDP数据转发
......@@ -41,7 +33,7 @@ public interface RtcService {
* @param sdpForwardParam
* @return
*/
ApiResult<Boolean> sdpForward(SdpForwardParam sdpForwardParam);
Boolean sdpForward(SdpForwardParam sdpForwardParam);
/**
* candidate候选者数据转发
......@@ -49,6 +41,6 @@ public interface RtcService {
* @param candidateForwardParam
* @return
*/
ApiResult<Boolean> candidateForward(CandidateForwardParam candidateForwardParam);
Boolean candidateForward(CandidateForwardParam candidateForwardParam);
}
package com.wecloud.rtc.service.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.im.param.rtc.*;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.im.ws.cache.UserStateListener;
import com.wecloud.rtc.entity.response.RtcCallResponse;
import com.wecloud.rtc.entity.response.RtcCandidateForwardResponse;
import com.wecloud.rtc.entity.response.RtcClientJoinResponse;
import com.wecloud.rtc.entity.response.RtcClientLeaveResponse;
import com.wecloud.rtc.entity.response.RtcClientRejectResponse;
import com.wecloud.rtc.entity.response.RtcSdpForwardResponse;
import com.wecloud.rtc.entity.response.*;
import com.wecloud.rtc.service.MangerRtcCacheService;
import com.wecloud.rtc.service.RtcService;
import com.wecloud.rtc.service.WsRtcWrite;
......@@ -82,7 +70,7 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
}
@Override
public ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam) {
public CreateRtcChannelResult createAndCall(CreateRtcChannelParam createRtcChannelParam) {
ImClient currentClient = imClientService.getCurrentClient();
Long rtcChannelId = SnowflakeUtil.getId();
// 判断发起方必须在线
......@@ -115,13 +103,13 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
// TODO 待开发 下发安卓和ios系统推送
return ApiResult.ok(createRtcChannelResult);
return createRtcChannelResult;
}
@Override
public ApiResult<Boolean> join(JoinRtcChannelParam joinRtcChannelParam) {
public Boolean join(JoinRtcChannelParam joinRtcChannelParam) {
ImClient client = imClientService.getCurrentClient();
......@@ -144,11 +132,11 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
wsRtcWrite.clientJoin(rtcSdpForwardResponse, Long.valueOf(toClientId));
}
return ApiResult.ok(true);
return true;
}
@Override
public ApiResult<Boolean> reject(RejectRtcChannelParam rejectRtcChannelParam) {
public Boolean reject(RejectRtcChannelParam rejectRtcChannelParam) {
ImClient client = imClientService.getCurrentClient();
// 修改缓存
mangerRtcCacheService.leave(client.getId(), rejectRtcChannelParam.getChannelId());
......@@ -169,20 +157,20 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
if (CollectionUtils.isEmpty(clientListByRtcChannelId)) {
// 移除频道信息
mangerRtcCacheService.delChannelInfo(rejectRtcChannelParam.getChannelId());
} else if (clientListByRtcChannelId.size() == 1){
} else if (clientListByRtcChannelId.size() == 1) {
// 频道内只有一个人了 -- 删除频道 并将这个人设为离开
mangerRtcCacheService.leave(Long.valueOf(clientListByRtcChannelId.get(0)), rejectRtcChannelParam.getChannelId());
mangerRtcCacheService.delChannelInfo(rejectRtcChannelParam.getChannelId());
}
return ApiResult.ok(true);
return true;
}
@Override
public ApiResult<Boolean> leave(LeaveRtcChannelParam leaveRtcChannelParam) {
public Boolean leave(LeaveRtcChannelParam leaveRtcChannelParam) {
ImClient currentClient = imClientService.getCurrentClient();
this.leave(leaveRtcChannelParam, currentClient);
return ApiResult.ok(true);
return true;
}
private void leave(LeaveRtcChannelParam leaveRtcChannelParam, ImClient currentClient) {
......@@ -206,7 +194,7 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
if (CollectionUtils.isEmpty(clientListByRtcChannelId)) {
// 移除频道信息
mangerRtcCacheService.delChannelInfo(leaveRtcChannelParam.getChannelId());
} else if (clientListByRtcChannelId.size() == 1){
} else if (clientListByRtcChannelId.size() == 1) {
// 频道内只有一个人了 -- 删除频道 并将这个人设为离开
mangerRtcCacheService.leave(Long.valueOf(clientListByRtcChannelId.get(0)), leaveRtcChannelParam.getChannelId());
mangerRtcCacheService.delChannelInfo(leaveRtcChannelParam.getChannelId());
......@@ -214,7 +202,7 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
}
@Override
public ApiResult<Boolean> sdpForward(SdpForwardParam sdpForwardParam) {
public Boolean sdpForward(SdpForwardParam sdpForwardParam) {
ImClient client = imClientService.getCurrentClient();
Long rtcChannelId = SnowflakeUtil.getId();
......@@ -251,11 +239,11 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
}
return ApiResult.ok(true);
return true;
}
@Override
public ApiResult<Boolean> candidateForward(CandidateForwardParam candidateForwardParam) {
public Boolean candidateForward(CandidateForwardParam candidateForwardParam) {
ImClient client = imClientService.getCurrentClient();
Long rtcChannelId = SnowflakeUtil.getId();
......@@ -291,7 +279,7 @@ public class RtcServiceImpl extends UserStateListener implements RtcService {
wsRtcWrite.candidateForward(rtcCandidateForwardResponse, Long.valueOf(toClientId));
}
return ApiResult.ok(true);
return true;
}
......
......@@ -22,7 +22,7 @@
</select>
<select id="getMyImConversationListAndMsgCount" resultType="com.wecloud.im.vo.ConversationVo">
SELECT imConversation.id,
SELECT imConversation.id as id,
imConversation.create_time,
imConversation.`name`,
imConversation.chat_type,
......
......@@ -29,7 +29,7 @@
friend.reject_remark, friend.request_remark, friend.state, friend.create_time
from im_friend friend inner join im_client client on friend.client_id_friend = client.client_id
inner join im_client claimer on friend.client_id_claimer = claimer.client_id
where friend.client_id = #{clientId} and friend.client_id_claimer != #{clientId}
where friend.client_id = #{clientId} and friend.client_id_claimer != #{clientId} order by friend.update_time desc
</select>
<select id="filterNegativeFriends" resultType="java.lang.String">
......
-- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本
-- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本
......@@ -119,6 +119,7 @@ CREATE TABLE `im_client_device`
-- 20220315 by wenzhida
DROP TABLE IF EXISTS `im_multi_rtc_room`;
CREATE TABLE `im_multi_rtc_room`
(
`id` bigint NOT NULL COMMENT '主键id',
......@@ -132,6 +133,7 @@ CREATE TABLE `im_multi_rtc_room`
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间表';
DROP TABLE IF EXISTS `im_multi_rtc_room_member`;
CREATE TABLE `im_multi_rtc_room_member`
(
`id` bigint NOT NULL COMMENT '主键id',
......@@ -141,11 +143,14 @@ CREATE TABLE `im_multi_rtc_room_member`
`client_id` varchar(200) DEFAULT NULL COMMENT '客户方提供的唯一id',
`state` tinyint NOT NULL DEFAULT '1' COMMENT '房间成员状态,1:呼叫中,2:已接听,3:已拒绝,4:未接听,5:已断开',
`call_time` timestamp NULL DEFAULT NULL COMMENT '呼叫时间',
`heartbeat_time` timestamp NULL DEFAULT NULL COMMENT '心跳时间',
`create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_fk_rtc_room_id` (`fk_rtc_room_id`) USING BTREE,
KEY `idx_room_id` (`room_id`) USING BTREE,
KEY `idx_call_time_state` (`call_time`, `state`) USING BTREE,
KEY `idx_heartbeat_time_state` (`heartbeat_time`, `state`) USING BTREE,
KEY `idx_client_id` (`client_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间成员表';
......
......@@ -68,10 +68,10 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger-ui</artifactId>-->
<!-- </dependency>-->
<!-- swagger end -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
......
<?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">
<groupId>com.wecloud</groupId>
<modelVersion>4.0.0</modelVersion>
<artifactId>im-sdk</artifactId>
<version>1.0</version>
<description>
蔚可云IM SDK
</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.7</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.67</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<!-- 绑定source插件到Maven的生命周期,并在生命周期后执行绑定的source的goal -->
<executions>
<execution>
<!-- 绑定source插件到Maven的生命周期 -->
<phase>compile</phase>
<!--在生命周期后执行绑定的source插件的goals -->
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.wecloud.im.sdk;
import com.wecloud.im.sdk.model.GetSignParam;
import com.wecloud.im.sdk.model.ImClient;
import com.wecloud.im.sdk.model.ImFriend;
import com.wecloud.im.sdk.model.ImTokenVerify;
import com.wecloud.im.sdk.model.Token;
/**
*
* @Author luozh
* @Date 2022年04月13日 11:09
* @Version 1.0
*/
public interface WecloudIm {
String sign(GetSignParam paramGetSignParam);
Token token(ImTokenVerify paramImTokenVerify);
ImClient getUserClient(Long paramLong);
Boolean createClient(Long paramLong, String paramString1, String paramString2, Integer paramInteger);
ImFriend getFriendInfo(Long paramLong1, Long paramLong2);
Boolean updateHeadPortrait(Long paramLong, String paramString);
Boolean updateNickname(Long paramLong, String paramString);
}
package com.wecloud.im.sdk;
import java.net.URI;
import com.wecloud.im.sdk.model.GetSignParam;
import com.wecloud.im.sdk.model.ImClient;
import com.wecloud.im.sdk.model.ImFriend;
import com.wecloud.im.sdk.model.ImTokenVerify;
import com.wecloud.im.sdk.model.Token;
/**
*
* @Author luozh
* @Date 2022年04月13日 11:23:24
* @Version 1.0
*/
public class WecloudImClient implements WecloudIm {
private URI endpoint;
private String appKey;
private String appSecret;
public WecloudImClient(URI endpoint, String appKey, String appSecret) {
this.endpoint = endpoint;
this.appKey = appKey;
this.appSecret = appSecret;
}
@Override
public String sign(GetSignParam signParam) {
return null;
}
@Override
public Token token(ImTokenVerify tokenVerify) {
return null;
}
@Override
public ImClient getUserClient(Long userId) {
return null;
}
@Override
public Boolean createClient(Long userId, String headPortrait, String nickname, Integer deviceType) {
return null;
}
@Override
public ImFriend getFriendInfo(Long clientId, Long userId) {
return null;
}
@Override
public Boolean updateHeadPortrait(Long clientId, String headPortrait) {
return null;
}
@Override
public Boolean updateNickname(Long clientId, String nickname) {
return null;
}
}
package com.wecloud.im.sdk;
import java.net.URI;
import java.net.URISyntaxException;
public class WecloudImClientBuilder {
public WecloudIm build(String endpoint, String appKey, String appSecret) {
try {
URI uri = new URI(endpoint);
return new WecloudImClient(uri, appKey, appSecret);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
}
package com.wecloud.im.sdk.common;
/**
* api code响应码
* @Author luozh
* @Date 2022年04月13日 10:58
* @Version 1.0
*/
public enum ApiCode {
/**
* 操作成功
**/
SUCCESS(200, "api.response.code.SUCCESS"),
/**
* 非法访问
**/
UNAUTHORIZED(401, "api.response.code.UNAUTHORIZED"),
/**
* 没有权限
**/
NOT_PERMISSION(403, "api.response.code.NOT_PERMISSION"),
/**
* 你请求的资源不存在
**/
NOT_FOUND(404, "api.response.code.NOT_FOUND"),
/**
* 操作失败
**/
FAIL(500, "api.response.code.FAIL"),
/**
* 登录失败
**/
LOGIN_EXCEPTION(4000, "api.response.code.LOGIN_EXCEPTION"),
/**
* 系统异常
**/
SYSTEM_EXCEPTION(5000, "api.response.code.SYSTEM_EXCEPTION"),
/**
* 请求参数校验异常
**/
PARAMETER_EXCEPTION(5001, "api.response.code.PARAMETER_EXCEPTION"),
/**
* 请求参数解析异常
**/
PARAMETER_PARSE_EXCEPTION(5002, "api.response.code.PARAMETER_PARSE_EXCEPTION"),
/**
* HTTP内容类型异常
**/
HTTP_MEDIA_TYPE_EXCEPTION(5003, "api.response.code.HTTP_MEDIA_TYPE_EXCEPTION"),
/**
* 系统处理异常
**/
SPRING_BOOT_PLUS_EXCEPTION(5100, "api.response.code.SPRING_BOOT_PLUS_EXCEPTION"),
/**
* 业务处理异常
**/
BUSINESS_EXCEPTION(5101, "api.response.code.BUSINESS_EXCEPTION"),
/**
* 数据库处理异常
**/
DAO_EXCEPTION(5102, "api.response.code.DAO_EXCEPTION"),
/**
* 验证码校验异常
**/
VERIFICATION_CODE_EXCEPTION(5103, "api.response.code.VERIFICATION_CODE_EXCEPTION"),
/**
* 登录授权异常
**/
AUTHENTICATION_EXCEPTION(5104, "api.response.code.AUTHENTICATION_EXCEPTION"),
/**
* 没有访问权限
**/
UNAUTHENTICATED_EXCEPTION(5105, "api.response.code.UNAUTHENTICATED_EXCEPTION"),
/**
* 没有访问权限
**/
UNAUTHORIZED_EXCEPTION(5106, "api.response.code.UNAUTHORIZED_EXCEPTION"),
/**
* JWT Token解析异常
**/
JWTDECODE_EXCEPTION(5107, "api.response.code.JWTDECODE_EXCEPTION"),
/**
* 默认的异常处理
*/
HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION(5108, "api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION"),
/**
* 已有会话,不能重复创建会话
*/
REPETITION_CONVERSATION(6010, "api.response.code.REPETITION_CONVERSATION"),
/**
* 成员不存在,不能创建会话
*/
CLIENT_NOT_FOUNT(6011, "api.response.code.CLIENT_NOT_FOUNT"),
/**
* 被对方拉黑
*/
IS_BE_BLACK(6012, "api.response.code.IS_BE_BLACK"),
/**
* 你把对方拉黑
*/
IS_TO_BLACK(6013, "api.response.code.IS_TO_BLACK"),
/**
* 已被踢出会话
*/
IS_BE_KICK_OUT(6014, "api.response.code.IS_BE_KICK_OUT"),
/**
* 已被禁言
*/
IS_BE_MUTED(6015, "api.response.code.IS_BE_MUTED"),
/**
* 群聊已解散
*/
IS_BE_DISBAND(6016, "api.response.code.IS_BE_DISBAND"),
;
private final int code;
private final String message;
ApiCode(final int code, final String message) {
this.code = code;
this.message = message;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
package com.wecloud.im.sdk.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
*
* @Author luozh
* @Date 2022年04月13日 10:59
* @Version 1.0
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 8004487252556526569L;
/**
* 响应码
*/
private int code;
/**
* 响应消息
*/
private String message;
/**
* 响应数据
*/
private T data;
public ApiResult() {
}
}
package com.wecloud.im.sdk.common;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import com.alibaba.fastjson.JSON;
/**
*
* @Author luozh
* @Date 2022年04月08日 18:20
* @Version 1.0
*/
public class HttpClient {
private static volatile OkHttpClient okHttpClient = null;
private static volatile Semaphore semaphore = null;
private Map<String, String> headerMap;
private Map<String, String> paramMap;
private String url;
private Request.Builder request;
/**
* 初始化okHttpClient,并且允许https访问
*/
private HttpClient() {
if (okHttpClient == null) {
synchronized (HttpClient.class) {
if (okHttpClient == null) {
TrustManager[] trustManagers = buildTrustManagers();
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
.hostnameVerifier((hostName, session) -> true)
.retryOnConnectionFailure(true)
.build();
addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
}
}
}
}
/**
* 用于异步请求时,控制访问线程数,返回结果
*
* @return
*/
private static Semaphore getSemaphoreInstance() {
//只能1个线程同时访问
synchronized (HttpClient.class) {
if (semaphore == null) {
semaphore = new Semaphore(0);
}
}
return semaphore;
}
/**
* 创建OkHttpUtils
*
* @return
*/
public static HttpClient builder() {
return new HttpClient();
}
/**
* 添加url
*
* @param url
* @return
*/
public HttpClient url(String url) {
this.url = url;
return this;
}
/**
* 添加参数
*
* @param key 参数名
* @param value 参数值
* @return
*/
public HttpClient addParam(String key, String value) {
if (paramMap == null) {
paramMap = new LinkedHashMap<>(16);
}
paramMap.put(key, value);
return this;
}
/**
* 添加请求头
*
* @param key 参数名
* @param value 参数值
* @return
*/
public HttpClient addHeader(String key, String value) {
if (headerMap == null) {
headerMap = new LinkedHashMap<>(16);
}
headerMap.put(key, value);
return this;
}
/**
* 初始化get方法
*
* @return
*/
public HttpClient get() {
request = new Request.Builder().get();
StringBuilder urlBuilder = new StringBuilder(url);
if (paramMap != null) {
urlBuilder.append("?");
try {
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).
append("=").
append(URLEncoder.encode(entry.getValue(), "utf-8")).
append("&");
}
} catch (Exception e) {
e.printStackTrace();
}
urlBuilder.deleteCharAt(urlBuilder.length() - 1);
}
request.url(urlBuilder.toString());
return this;
}
/**
* 初始化post方法
*
* @param isJsonPost true等于json的方式提交数据,类似postman里post方法的raw
* false等于普通的表单提交
* @return
*/
public HttpClient post(boolean isJsonPost) {
RequestBody requestBody;
if (isJsonPost) {
String json = "";
if (paramMap != null) {
json = JSON.toJSONString(paramMap);
}
requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
} else {
FormBody.Builder formBody = new FormBody.Builder();
if (paramMap != null) {
paramMap.forEach(formBody::add);
}
requestBody = formBody.build();
}
request = new Request.Builder().post(requestBody).url(url);
return this;
}
/**
* 同步请求
*
* @return
*/
public String sync() {
setHeader(request);
try {
Response response = okHttpClient.newCall(request.build()).execute();
assert response.body() != null;
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
return "请求失败:" + e.getMessage();
}
}
/**
* 异步请求,有返回值
*/
public String async() {
StringBuilder buffer = new StringBuilder("");
setHeader(request);
okHttpClient.newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
buffer.append("请求出错:").append(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
assert response.body() != null;
buffer.append(response.body().string());
getSemaphoreInstance().release();
}
});
try {
getSemaphoreInstance().acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
return buffer.toString();
}
/**
* 异步请求,带有接口回调
*
* @param callBack
*/
public void async(ICallBack callBack) {
setHeader(request);
okHttpClient.newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFailure(call, e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
assert response.body() != null;
callBack.onSuccessful(call, response.body().string());
}
});
}
/**
* 为request添加请求头
*
* @param request
*/
private void setHeader(Request.Builder request) {
if (headerMap != null) {
try {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
request.addHeader(entry.getKey(), entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 生成安全套接字工厂,用于https请求的证书跳过
*
* @return
*/
private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return ssfFactory;
}
private static TrustManager[] buildTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
/**
* 自定义一个接口回调
*/
public interface ICallBack {
void onSuccessful(Call call, String data);
void onFailure(Call call, String errorMsg);
}
}
package com.wecloud.im.sdk.enums;
/**
* @Author wenzhida
* @Date 2022/3/2 17:15
* @Description 设备类型枚举
*/
public enum DeviceTypeEnum {
IOS(1, "IOS端"),
ANDROID(2, "安卓端"),
WEB(3, "web端"),
WIN(4, "PC-windows端"),
MAC(5, "PC-macOs端");
private final Integer code;
private final String desc;
DeviceTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
}
package com.wecloud.im.sdk.model;
import lombok.Data;
import java.io.Serializable;
/**
* sign
*
* @author wei
* @since 2021-04-29
*/
@Data
public class GetSignParam implements Serializable {
private static final long serialVersionUID = 1L;
private String timestamp;
private String clientId;
private String appKey;
private Integer platform;
private String appSecret;
}
package com.wecloud.im.sdk.model;
import lombok.Data;
import java.util.Date;
/**
* 终端表
*
* @author wei
* @since 2021-04-27
*/
@Data
public class ImClient {
private static final long serialVersionUID = 1L;
private Long id;
private Date createTime;
private Date lastOfflineTime;
private Date updateTime;
private Long fkAppid;
private String attributes;
private String clientId;
private String headPortrait;
private String nickname;
}
package com.wecloud.im.sdk.model;
import lombok.Data;
/**
*
* @Author luozh
* @Date 2022年04月13日 11:03
* @Version 1.0
*/
@Data
public class ImFriend {
private static final long serialVersionUID = 1L;
private Long id;
private String clientId;
private String clientIdFriend;
private String clientIdClaimer;
private String friendName;
private String rejectRemark;
private String requestRemark;
private Integer state;
}
package com.wecloud.im.sdk.model;
import lombok.Data;
/**
* token 校验
*
* @author wei
* @since 2021-04-29
*/
@Data
public class ImTokenVerify {
private static final long serialVersionUID = 1L;
/**
* 时间戳,需与生成sign时的值一致
*/
private String timestamp;
/**
* client客户端id,需与生成sign时的值一致
*/
private String clientId;
/**
* appkey,需与生成sign时的值一致
*/
private String appKey;
/**
* 客户端平台: 1 web, 2 安卓, 3 ios, 4 pc-win, 5 pc-macOs, 需与生成sign时的值一致
*/
private Integer platform;
/**
* 签名sign
*/
private String sign;
}
package com.wecloud.im.sdk.model;
import lombok.Data;
/**
*
* @Author luozh
* @Date 2022年04月13日 11:07
* @Version 1.0
*/
@Data
public class Token {
/**
* websocket登陆令牌
*/
private String token;
/**
* 客户端id
*/
private Long id;
/**
* webSocket连接地址
*/
private String wsAddr;
/**
* 加密密钥
*/
private String dataAesKey;
/**
* 可选 自定义属性,供开发者扩展使用。
*/
private String attributes;
}
......@@ -68,6 +68,8 @@
<module>generator</module>
<module>core</module>
<module>client</module>
<module>scheduled</module>
<module>im-sdk</module>
<!-- <module>api-app</module>-->
<!-- <module>distribution</module>-->
<!-- <module>admin</module>-->
......@@ -158,11 +160,11 @@
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger-ui</artifactId>-->
<!-- <version>${swagger2.version}</version>-->
<!-- </dependency>-->
<!-- swagger end -->
<dependency>
......
......@@ -15,10 +15,12 @@
<description>任务调度JOB模块</description>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>io.geekidea.springbootplus</groupId>-->
<!-- <artifactId>example</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>io.geekidea.springbootplus</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
</project>
......@@ -31,7 +31,7 @@ public class HelloScheduled {
/**
* 每小时执行一次
*/
@Scheduled(cron = "0 0 0/1 * * ? ")
// @Scheduled(cron = "*/5 * * * * ? ")
public void hello() throws Exception {
log.info("HelloScheduled...");
}
......
package io.geekidea.springbootplus.scheduled;
import com.wecloud.multimeet.service.MultiMeetService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @Author wenzhida
* @Date 2022/3/28 16:34
* @Description 多人音视频相关定时器
*/
@Slf4j
@Component
public class MultiMeetScheduled {
@Autowired
private MultiMeetService multiMeetService;
/**
* 呼叫超时处理
* 每5秒执行一次
*/
@Scheduled(cron = "*/5 * * * * ?")
public void callingTimeout() {
log.info("呼叫超时处理开始...");
multiMeetService.callingTimeout();
log.info("呼叫超时处理结束...");
}
/**
* 接听中成员异常断线处理
* 每10秒执行一次 (5秒一次心跳 - 20秒未收到心跳,认为已经异常断开连接)
*/
@Scheduled(cron = "*/10 * * * * ?")
public void disconnect() {
log.info("异常断线处理开始...");
multiMeetService.disconnect();
log.info("异常断线处理结束...");
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment