feat: 提供客户端模拟机器人文本消息、普通用户文本消息的接口

This commit is contained in:
songyuanlun 2024-01-08 18:24:51 +08:00
parent 1d24adfb06
commit 60b650ecd6
6 changed files with 269 additions and 8 deletions

View File

@ -0,0 +1,28 @@
package cn.axzo.im.center.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 渠道消息类型
*/
@Getter
@AllArgsConstructor
public enum ChannelMsgTypeEnum {
/**
* 文本
*/
TEXT(0, "文本消息"),
/**
* 自定义
*/
CUSTOM(100, "自定义消息"),
;
private final Integer code;
private final String message;
}

View File

@ -3,7 +3,17 @@ package cn.axzo.im.channel.netease;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.dto.*;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchResponse;
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchResponse;
import cn.axzo.im.channel.netease.dto.MessageDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageDispatchResponse;
import cn.axzo.im.channel.netease.dto.NimAccountInfo;
import cn.axzo.im.channel.netease.dto.QueryAccountResp;
import cn.axzo.im.channel.netease.dto.RegisterRequest;
import cn.axzo.im.channel.netease.dto.RegisterResponse;
import cn.axzo.im.channel.netease.dto.RegisterUpdateRequest;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
@ -11,17 +21,16 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import javax.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 网易云信IM服务
*
@ -149,7 +158,6 @@ public class NimChannelService implements IMChannelProvider {
}
//目前支持的默认值 0单聊消息 100自定义消息
messageInfo.setOpe(MSG_OPE);
messageInfo.setType(MSG_TYPE);
HashMap<String, Object> paramMap = Maps.newHashMap();
paramMap.put("from", messageInfo.getFrom());
paramMap.put("body", messageInfo.getBody());

View File

@ -0,0 +1,176 @@
package cn.axzo.im.controller;
import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.ChannelMsgTypeEnum;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.dto.MessageDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageDispatchResponse;
import cn.axzo.im.channel.netease.dto.RegisterUpdateRequest;
import cn.axzo.im.entity.AccountRegister;
import cn.axzo.im.entity.bo.AccountQueryParam;
import cn.axzo.im.service.AccountService;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author syl
* @date 2024/1/8
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/private/message")
public class PrivateMessageController {
@Autowired
private IMChannelProvider imChannel;
@Autowired
private AccountService accountService;
@PostMapping(value = "/send")
public CommonResponse<List<MessageDispatchResp>> sendMessage(@RequestBody @Valid SendMessageRequest param) {
log.info("send message param: [{}]", JSONUtil.toJsonStr(param));
String appKey = imChannel.getProviderAppKey();
List<MessageDispatchResp> result = Lists.newArrayList();
List<AccountRegister> accounts = accountService.listAccount(
AccountQueryParam.builder().accountType(param.getSenderType())
.accountId(param.getSenderId())
.appKey(appKey).build());
if (CollUtil.isEmpty(accounts)) {
log.info("appKey= [{}], senderId= [{}] 用户没有注册im账号, 请检查",
appKey, param.getSenderId());
return CommonResponse.success(result);
}
AccountRegister account = accounts.get(0);
if (param.getSenderType() == AccountTypeEnum.USER) {
// 更新用户头像和昵称到网易云信
updateUserProfile(param, account);
}
param.getAppTypeList().forEach(type -> {
List<AccountRegister> receivers = accountService.listAccount(
AccountQueryParam.builder().accountId(param.getToPersonId())
.appKey(appKey)
.appType(type).build());
if (CollUtil.isEmpty(receivers)) {
log.info("appKey= [{}], appType= [{}], receiverId= [{}] 用户没有注册im账号, 请检查",
appKey, type, param.getToPersonId());
return;
}
AccountRegister receiver = receivers.get(0);
MessageDispatchRequest messageRequest = new MessageDispatchRequest();
messageRequest.setFrom(account.getImAccount());
messageRequest.setTo(receiver.getImAccount());
messageRequest.setType(param.getChannelMsgType().getCode());
// 暂时支持客户端的文本消息其他后续扩展
messageRequest.setBody(new JSONObject().fluentPut("msg", param.getMsgContent()).toJSONString());
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
log.info("send text message= [{}]", JSONUtil.toJsonStr(response));
MessageDispatchResp messageDispatchResp = BeanUtil.copyProperties(response.getData(),
MessageDispatchResp.class);
if (StringUtils.isNotBlank(response.getDesc())) {
messageDispatchResp.setDesc(response.getDesc());
}
messageDispatchResp.setAppType(type.getCode());
messageDispatchResp.setFromImAccount(messageRequest.getFrom());
messageDispatchResp.setToImAccount(messageRequest.getTo());
messageDispatchResp.setPersonId(param.getToPersonId());
result.add(messageDispatchResp);
});
return CommonResponse.success(result);
}
private void updateUserProfile(SendMessageRequest param, AccountRegister account) {
if (Objects.isNull(param.getExt())) {
log.info("普通用户不用更新 头像昵称, personId= [{}]", account.getAccountId());
return;
}
String extJson = new JSONObject().fluentPut("accountType", AccountTypeEnum.USER.getCode()).toJSONString();
RegisterUpdateRequest updateProfile = new RegisterUpdateRequest();
updateProfile.setAccid(account.getImAccount());
updateProfile.setName(param.getExt().getString("nickName"));
updateProfile.setIcon(param.getExt().getString("avatarUrl"));
updateProfile.setExtJson(extJson);
log.info("updateUserProfile:{}", JSONUtil.toJsonStr(updateProfile));
imChannel.updateAccountProfile(updateProfile);
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class SendMessageRequest {
/**
* 发送消息到App端 工人端企业端服务器 CMCMPSYSTEM
*
* @See cn.axzo.im.center.common.enums.AppTypeEnum
*/
@NotNull(message = "消息接收端类型appTypeList不能为空")
private List<AppTypeEnum> appTypeList;
/**
* 发送者类型
*/
@NotNull(message = "发送者类型不能为空")
private AccountTypeEnum senderType;
/**
* 发送用户Id
*/
@NotBlank(message = "发送用户Id")
private String senderId;
/**
* 接收用户自然人Id
*/
@NotBlank(message = "接收用户自然人Id不能为空")
private String toPersonId;
/**
* 渠道消息类型
*/
@NotNull(message = "渠道消息类型不能为空")
private ChannelMsgTypeEnum channelMsgType;
/**
* 消息内容
*/
@NotBlank(message = "消息内容不能为空")
private String msgContent;
/**
* 扩展信息
*/
private JSONObject ext;
}
}

View File

@ -0,0 +1,25 @@
package cn.axzo.im.entity.bo;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author syl
* @date 2024/1/6
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AccountQueryParam {
private AccountTypeEnum accountType;
private AppTypeEnum appType;
private String appKey;
private String accountId;
}

View File

@ -19,6 +19,8 @@ import cn.axzo.im.dao.repository.AccountRegisterDao;
import cn.axzo.im.dao.repository.RobotInfoDao;
import cn.axzo.im.entity.AccountRegister;
import cn.axzo.im.entity.RobotInfo;
import cn.axzo.im.entity.bo.AccountQueryParam;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.collect.Lists;
import java.util.Date;
import java.util.List;
@ -292,4 +294,24 @@ public class AccountService {
}
return userAccountAll;
}
public List<AccountRegister> listAccount(AccountQueryParam param) {
return build(param).list();
}
public LambdaQueryChainWrapper<AccountRegister> build(AccountQueryParam param) {
LambdaQueryChainWrapper<AccountRegister> lambdaQuery = accountRegisterDao.lambdaQuery()
.eq(AccountRegister::getIsDelete, 0)
.eq(StringUtils.isNotBlank(param.getAppKey()), AccountRegister::getAppKey, param.getAppKey())
.eq(StringUtils.isNotBlank(param.getAccountId()), AccountRegister::getAccountId, param.getAccountId())
.isNotNull(AccountRegister::getToken);
if (Objects.nonNull(param.getAccountType())) {
lambdaQuery.eq(AccountRegister::getAccountType, param.getAccountType().getCode());
}
if (Objects.nonNull(param.getAppType())) {
lambdaQuery.eq(AccountRegister::getAppType, param.getAppType().getCode());
}
return lambdaQuery;
}
}

View File

@ -11,6 +11,7 @@ import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.api.vo.resp.UserAccountResp;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.ChannelMsgTypeEnum;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.NimMsgTypeEnum;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
@ -305,6 +306,7 @@ public class MessageService {
if (StringUtils.isNotEmpty(accountRegister.getImAccount()) &&
StringUtils.isNotEmpty(accountRegister.getToken())) {
messageRequest.setTo(accountRegister.getImAccount());
messageRequest.setType(ChannelMsgTypeEnum.CUSTOM.getCode());
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
MessageDispatchResp messageDispatchResp = BeanMapper.map(response.getData(), MessageDispatchResp.class);
if (messageDispatchResp == null) {