大家都一样的《计谋模式》

打印 上一主题 下一主题

主题 838|帖子 838|积分 2524

不同类型的消息处理

这里抽象层用的是接口
MessageProcess  ⬇︎⬇︎⬇︎
点击查看代码
  1. /**
  2. * 消息处理
  3. *
  4. * @author haiyang
  5. */
  6. public interface MessageProcess<K,V> {
  7.     /**
  8.      * 处理消息
  9.      *
  10.      * @param messageInfo 消息相关信息
  11.      * @return {@link V}
  12.      */
  13.     V dealWithMessage(final K messageInfo);
  14. }
复制代码
客户的消息 CustomerMessageProcess ⬇︎⬇︎⬇︎
点击查看代码
  1. /**
  2. * 客户消息
  3. * <pre>
  4. *     客户回复的消息如果是数字,需要将数字对应的detail和可选项回复关联起来。
  5. * </pre>
  6. *
  7. * @author haiyang
  8. */
  9. public class CustomerMessageProcess implements MessageProcess<MessageFullInfoDto, MessageProcessFinalResultDto> {
  10.     @Override
  11.     public MessageProcessFinalResultDto dealWithMessage(final MessageFullInfoDto messageFullInfoDto) {
  12.         // 判断是否处于禁止发言期间
  13.         Object disableReplay = redisUtils.get(RedisKeyUtil.getDisableReplayKey(messageFullInfoDto.getRoomId()));
  14.         if (!Objects.isNull(disableReplay)) {
  15.             log.info("群:{}正处于禁止机器人发言期", messageFullInfoDto.getRoomId());
  16.             return new MessageProcessFinalResultDto(false, "正处于禁止机器人发言期", null);
  17.         }
  18.         // 判断文本是否属于数字类型
  19.         String messageContents = messageFullInfoDto.getMessageContents();
  20.         boolean numeric = StringUtils.isNumeric(messageContents);
  21.         Long groupId = messageFullInfoDto.getGroupId();
  22.         if (numeric) {
  23.             // 走数字逻辑
  24.             int parseInt = Integer.parseInt(messageContents);
  25.             if (parseInt > 0 && parseInt <= 10) {
  26.                 LambdaQueryWrapper<MsgDetail> lastDetail = new LambdaQueryWrapper<MsgDetail>().eq(MsgDetail::getGroupId, groupId).eq(MsgDetail::getType, MsgDetailEnum.Type.REPLY.getCode()).orderByDesc(MsgDetail::getCreateTime).last("limit 1");
  27.                 MsgDetail replyMsgDetail = msgDetailService.getOne(lastDetail);
  28.                 MessageProcessFinalResultDto messageProcessFinalResultDto = noOptionReplyHandler(messageFullInfoDto, messageContents, groupId, replyMsgDetail);
  29.                 if (messageProcessFinalResultDto != null) {
  30.                     return messageProcessFinalResultDto;
  31.                 }
  32.                 MsgAnswers groupLastAnswer = msgAnswersService.getGroupLastAnswer(groupId, parseInt);
  33.                 messageProcessFinalResultDto = missedReplyHandler(messageFullInfoDto, messageContents, groupId, groupLastAnswer);
  34.                 if (messageProcessFinalResultDto != null) {
  35.                     return messageProcessFinalResultDto;
  36.                 }
  37.                 messageProcessFinalResultDto = handlerInvalidate(messageFullInfoDto, messageContents, groupId, groupLastAnswer);
  38.                 if (messageProcessFinalResultDto != null) {
  39.                     return messageProcessFinalResultDto;
  40.                 }
  41.                 messageProcessFinalResultDto = hitHandler(messageFullInfoDto, messageContents, groupId, groupLastAnswer);
  42.                 String replyDetailId = replyMsgDetail.getReplyDetailId();
  43.                 if (StringUtils.isNotEmpty(replyDetailId)) {
  44.                     replyDetailId += "," + messageProcessFinalResultDto.getExtendData();
  45.                 } else {
  46.                     replyDetailId = "" + messageProcessFinalResultDto.getExtendData();
  47.                 }
  48.                 replyMsgDetail.setReplyDetailId(replyDetailId);
  49.                 msgDetailService.updateById(replyMsgDetail);
  50.                 return messageProcessFinalResultDto;
  51.             }
  52.         }
  53.         // 普通文本处理
  54.         saveDetail(messageFullInfoDto, messageContents, groupId, null, true);
  55.         LambdaQueryWrapper<MsgWaitTask> queryWrapper = new LambdaQueryWrapper<MsgWaitTask>().eq(MsgWaitTask::getGroupId, groupId).eq(MsgWaitTask::getMergeStatus, MergeStatusEnum.WAIT_MERGE.getStatus()).orderByDesc(MsgWaitTask::getWaitMergeTime).last("limit 1");
  56.         MsgWaitTask msgWaitTask = msgWaitTaskService.getOne(queryWrapper);
  57.         if (Objects.isNull(msgWaitTask)) {
  58.             saveMsgWaitTask(messageFullInfoDto, groupId);
  59.             return new MessageProcessFinalResultDto(true, null, null);
  60.         }
  61.         LocalDateTime waitMergeTime = msgWaitTask.getWaitMergeTime();
  62.         LocalDateTime now = LocalDateTime.now();
  63.         if (now.isAfter(waitMergeTime)) {
  64.             saveMsgWaitTask(messageFullInfoDto, groupId);
  65.         } else {
  66.             // 更新整合时间和最后一次微信时间
  67.             msgWaitTask.setLastTxMsgTime(messageFullInfoDto.getMsgTime());
  68.             msgWaitTask.setWaitMergeTime(LocalDateTime.now().plusSeconds(15));
  69.             msgWaitTaskService.updateById(msgWaitTask);
  70.         }
  71.         return new MessageProcessFinalResultDto(true, null, null);
  72.     }
  73.     private void saveMsgWaitTask(MessageFullInfoDto messageFullInfoDto, Long groupId) {
  74.         MsgWaitTask msgWaitTask;
  75.         // 说明已经过了整合时间, 重新插入一条数据
  76.         msgWaitTask = new MsgWaitTask();
  77.         msgWaitTask.setGroupId(groupId);
  78.         msgWaitTask.setRoomId(messageFullInfoDto.getRoomId());
  79.         Long msgTime = messageFullInfoDto.getMsgTime();
  80.         msgWaitTask.setWaitMergeTime(LocalDateTime.now().plusSeconds(15));
  81.         msgWaitTask.setLastTxMsgTime(msgTime);
  82.         msgWaitTask.setMergeStatus(MergeStatusEnum.WAIT_MERGE.getStatus());
  83.         msgWaitTaskService.save(msgWaitTask);
  84.     }
  85.     /**
  86.      * 命中处理
  87.      */
  88.     private MessageProcessFinalResultDto hitHandler(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId, MsgAnswers groupLastAnswer) {
  89.         String answerContext = groupLastAnswer.getAnswerContext();
  90.         Long rpaMsgDetailId = saveRpaMsgDetail(messageFullInfoDto, groupId, answerContext);
  91.         // 保存客户detail
  92.         Long detailId = saveDetail(messageFullInfoDto, messageContents, groupId, rpaMsgDetailId, false);
  93.         // 发送rpa任务
  94.         sendRpaTask(messageFullInfoDto, answerContext, rpaMsgDetailId,TaskSubTypeEnum.ACCURATE.getType());
  95.         return new MessageProcessFinalResultDto(true, null, detailId);
  96.     }
  97.     /**
  98.      * 无可选项回复处理
  99.      */
  100.     private MessageProcessFinalResultDto noOptionReplyHandler(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId, MsgDetail replyMsgDetail) {
  101.         if (Objects.isNull(replyMsgDetail) || DateUtil.isAfterMinus(replyMsgDetail.getCreateTime(), 20)) {
  102.             // 没有可选项回复 存入detail 不执行回复
  103.             saveDetail(messageFullInfoDto, messageContents, groupId, null, false);
  104.             log.info("客服发言的数字文本无需回复, fromAccount:{}, textContext:{}", messageFullInfoDto.getFromAccount(), messageContents);
  105.             noWorkAutoReply(messageFullInfoDto, messageContents, groupId);
  106.             return new MessageProcessFinalResultDto(true, null, null);
  107.         }
  108. /*       // 判断可选项时间是否在20min有效期
  109.         LocalDateTime createTime = replyMsgDetail.getCreateTime();
  110.         if (DateUtil.isAfterMinus(createTime, 20)) {
  111.             // 超过了有效期, 回复默认文本
  112.             // 没有可选项回复 存入detail 不执行回复
  113.             saveDetail(messageFullInfoDto, messageContents, groupId, null, false);
  114.             log.info("客服发言的数字文本无需回复, fromAccount:{}, textContext:{}", messageFullInfoDto.getFromAccount(), messageContents);
  115.             return new MessageProcessFinalResultDto(true, null, null);
  116.         }*/
  117.         return null;
  118.     }
  119.     private void noWorkAutoReply(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId) {
  120.         // 非工自动回复处理
  121.         boolean workTime = DateUtil.workTime(new Date());
  122.         if (!workTime) {
  123.             Object noWorkReplay = redisUtils.get(RedisKeyUtil.getNoWorkReplayKey(messageFullInfoDto.getRoomId()));
  124.             if (Objects.isNull(noWorkReplay)) {
  125.                 // 发送rpa任务 推送非工时间的默认回复
  126.                 String noWorkAutoReply = ianswerProperties.getNoWorkAutoReply();
  127.                 Long rpaMsgDetailId = saveRpaMsgDetail(messageFullInfoDto, groupId, noWorkAutoReply);
  128.                 // 保存客户detail
  129.                 saveDetail(messageFullInfoDto, messageContents, groupId, rpaMsgDetailId, false);
  130.                 // 发送rpa任务
  131.                 sendRpaTask(messageFullInfoDto, noWorkAutoReply, rpaMsgDetailId,TaskSubTypeEnum.ACCURATE.getType());
  132.                 // 计算非工回复周期
  133.                 int tomorrowSeconds = DateUtil.getTomorrowSeconds(new Date());
  134.                 redisUtils.setWithExpireSeconds(RedisKeyUtil.getNoWorkReplayKey(messageFullInfoDto.getRoomId()),  true, tomorrowSeconds);
  135.             }
  136.         }
  137.     }
  138.     /**
  139.      * 未命中处理
  140.      */
  141.     private MessageProcessFinalResultDto missedReplyHandler(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId, MsgAnswers groupLastAnswer) {
  142.         if (Objects.isNull(groupLastAnswer)) {
  143.             // 保存机器人默认回复文本
  144.             String missedReply = ianswerProperties.getMissedReply();
  145.             Long rpaMsgDetailId = saveRpaMsgDetail(messageFullInfoDto, groupId, missedReply);
  146.             // 保存客户detail
  147.             saveDetail(messageFullInfoDto, messageContents, groupId, rpaMsgDetailId, false);
  148.             // 发送rpa任务
  149.             sendRpaTask(messageFullInfoDto, missedReply, rpaMsgDetailId,TaskSubTypeEnum.FIXED.getType());
  150.             return new MessageProcessFinalResultDto(true, null, null);
  151.         }
  152.         return null;
  153.     }
  154.     /**
  155.      * 以上都不是处理
  156.      */
  157.     private MessageProcessFinalResultDto handlerInvalidate(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId, MsgAnswers groupLastAnswer) {
  158.         if (MsgAnswerEnum.Type.INVALIDATE.getCode().equals(groupLastAnswer.getType())) {
  159.             // 以上都不是, 需要回复固定话术
  160.             boolean workTime = DateUtil.workTime(new Date());
  161.             String textContext = null;
  162.             if (workTime) {
  163.                 textContext = ianswerProperties.getExitWork();
  164.             } else {
  165.                 textContext = ianswerProperties.getExitNonWork();
  166.             }
  167.             Long rpaMsgDetailId = saveRpaMsgDetail(messageFullInfoDto, groupId, textContext);
  168.             // 保存客户detail
  169.             saveDetail(messageFullInfoDto, messageContents, groupId, rpaMsgDetailId, false);
  170.             // 发送rpa任务
  171.             sendRpaTask(messageFullInfoDto, textContext, rpaMsgDetailId,TaskSubTypeEnum.FIXED.getType());
  172.             return new MessageProcessFinalResultDto(true, null, null);
  173.         }
  174.         return null;
  175.     }
  176.     private void sendRpaTask(MessageFullInfoDto messageFullInfoDto, String missedReply, Long rpaMsgDetailId,String taskSubType) {
  177.         SendTaskDto sendTaskDto = new SendTaskDto();
  178.         sendTaskDto.setRoomId(messageFullInfoDto.getRoomId());
  179.         sendTaskDto.setDetailId(rpaMsgDetailId);
  180.         sendTaskDto.setContentSign(messageContextUtil.getSHAStr(missedReply));
  181.         sendTaskDto.setGroupId(messageFullInfoDto.getGroupId());
  182.         SendTaskRequest sendTaskRequest = new SendTaskRequest();
  183.         sendTaskRequest.setContent(missedReply);
  184.         sendTaskRequest.setResourceName(messageFullInfoDto.getOrderNo());
  185.         sendTaskRequest.setWaitingRobotAccounts(messageFullInfoDto.getRobotAccount());
  186.         sendTaskRequest.setWaitingRobotNames(messageFullInfoDto.getRobotName());
  187.         sendTaskRequest.setTaskOverTime(DateUtil.addTimeToString(LocalDateTime.now(), 30));
  188.         sendTaskRequest.setCustomer(messageFullInfoDto.getCustomName());
  189.         sendTaskRequest.setSubResourceName(messageFullInfoDto.getGrowthMember());
  190.         sendTaskRequest.setOrderId(messageFullInfoDto.getOrderNo());
  191.         sendTaskRequest.setTaskSubType(taskSubType);
  192.         sendTaskDto.setSendTaskRequest(sendTaskRequest);
  193.         rpaTaskService.sendTask(sendTaskDto);
  194.     }
  195.     private Long saveRpaMsgDetail(MessageFullInfoDto messageFullInfoDto, Long groupId, String missedReply) {
  196.         MsgDetail msgDetail = new MsgDetail();
  197.         msgDetail.setType(MsgDetailEnum.Type.COMMON.getCode());
  198.         msgDetail.setGroupId(groupId);
  199.         msgDetail.setRoomId(messageFullInfoDto.getRoomId());
  200.         msgDetail.setMsgStatus(MsgDetailEnum.MsgStatus.TO_BE_RECEIVE.getCode());
  201.         msgDetail.setTextContext(missedReply);
  202.         msgDetail.setTextContextSign(messageContextUtil.getSHAStr(missedReply));
  203.         msgDetail.setMergeStatus(MsgDetailEnum.MergeStatus.NONE.getCode());
  204.         msgDetail.setReplyStatus(MsgDetailEnum.ReplyStatus.WAIT_REPLY.getCode());
  205.         msgDetail.setSendAccountType(MsgDetailEnum.SendAccountType.RPA.getCode());
  206.         msgDetail.setSendQwName(messageFullInfoDto.getRobotName());
  207.         msgDetail.setSendQwAccount(messageFullInfoDto.getRobotAccount());
  208.         msgDetailService.save(msgDetail);
  209.         return msgDetail.getId();
  210.     }
  211.     private Long saveDetail(MessageFullInfoDto messageFullInfoDto, String messageContents, Long groupId, Long rpaMsgDetailId, boolean isTextMessage) {
  212.         MsgDetail msgDetail = new MsgDetail();
  213.         msgDetail.setType(MsgDetailEnum.Type.COMMON.getCode());
  214.         msgDetail.setGroupId(groupId);
  215.         msgDetail.setRoomId(messageFullInfoDto.getRoomId());
  216.         msgDetail.setMsgId(messageFullInfoDto.getMsgId());
  217.         msgDetail.setMsgTime(messageFullInfoDto.getMsgTime());
  218.         msgDetail.setMsgFrom(messageFullInfoDto.getFromAccount());
  219.         msgDetail.setMsgStatus(MsgDetailEnum.MsgStatus.RECEIVED.getCode());
  220.         msgDetail.setTextContext(messageContents);
  221.         msgDetail.setTextContextSign(messageContextUtil.getSHAStr(messageContents));
  222.         if (isTextMessage) {
  223.             msgDetail.setMergeStatus(MsgDetailEnum.MergeStatus.WAIT_MERGE.getCode());
  224.             msgDetail.setReplyStatus(MsgDetailEnum.ReplyStatus.WAIT_REPLY.getCode());
  225.         } else {
  226.             msgDetail.setReplyStatus(MsgDetailEnum.ReplyStatus.NONE.getCode());
  227.             msgDetail.setMergeStatus(MsgDetailEnum.MergeStatus.NONE.getCode());
  228.         }
  229.         if (Objects.nonNull(rpaMsgDetailId)) {
  230.             msgDetail.setReplyDetailId(rpaMsgDetailId.toString());
  231.         }
  232.         msgDetailService.save(msgDetail);
  233.         return msgDetail.getId();
  234.     }
  235. }
复制代码
人工客服消息 StaffServiceMessageProcess ⬇︎⬇︎⬇︎
点击查看代码
  1. /**
  2. * 机器人消息
  3. * <pre>
  4. *     整体处理逻辑:
  5. *     1.根据群id和机器人的账号+内容签名,确定一条最新的有效的明细和任务
  6. *     2.更新机器人发言的那条明细记录
  7. *     3.更新rpa任务相应的状态
  8. *     4.更新前面整合提问的那些明细
  9. * </pre>
  10. *
  11. * @author haiyang
  12. */
  13. @Component
  14. @Slf4j
  15. public class RobotMessageProcess implements MessageProcess<MessageFullInfoDto, MessageProcessFinalResultDto> {
  16.     @Override
  17.     public MessageProcessFinalResultDto dealWithMessage(final MessageFullInfoDto messageInfo) {
  18.         log.info("RobotMessageProcess params:{}",JSON.toJSONString(messageInfo));
  19.         // 1.查到对应的rpa task 和 msg detail(这个消息是机器人发送的消息)
  20.         TaskMsgDetailDto taskDetailInfo = rpaTaskService.getTaskDetailInfo(messageInfo.getRoomId(),
  21.                 messageInfo.getFromAccount(),
  22.                 getShaContentsOfTrimAt(messageInfo.getMessageContents())
  23.         );
  24.         log.info("getTaskDetailInfo result:{}", JSON.toJSONString(taskDetailInfo));
  25.         if (Objects.isNull(taskDetailInfo)) {
  26.             return new MessageProcessFinalResultDto(false,"没有找到对应的task detail",null);
  27.         }
  28.         // 2.更新 rpa task 中的 rpa_msg_status
  29.         rpaTaskService.updateRpaMsgStatus(taskDetailInfo.getTaskId(), RpaTaskEnum.RpaMsgStatus.RECEIVE_SUCCESS.getCode());
  30.         log.info("更新rpa task的状态--完成");
  31.         // 3.更新机器人消息的detail的中的 msg_status 状态 ,
  32.         // 同时需要更新对应的 send_qw_name 和 send_qw_account 为实际发送消息的robot账号信息(实际回复消息的只有一个机器人)
  33.         msgDetailService.updateMsgStatus(taskDetailInfo.getDetailId(),
  34.                 MsgDetailEnum.MsgStatus.RECEIVED.getCode(),
  35.                 messageInfo.getFromAccountName(),
  36.                 messageInfo.getFromAccount(),
  37.                 messageInfo.getMsgId(),
  38.                 messageInfo.getMsgTime(),
  39.                 messageInfo.getFromAccount());
  40.         log.info("更新robot消息detail的状态--完成");
  41.         // 4.更新对应的整合消息的 reply_status
  42.         msgDetailService.refreshReplyStatus(taskDetailInfo.getDetailId(),taskDetailInfo.getMsgId(),taskDetailInfo.getMsgTime());
  43.         log.info("更新对应的整合消息--完成");
  44.         syncNotifyListener(taskDetailInfo);
  45.         log.info("通知操作--完成");
  46.         return new MessageProcessFinalResultDto(true,null,null);
  47.     }
  48.     /**
  49.      * 将机器人消息去除@符号进行签名
  50.      * <pre>
  51.      *     <b>下发rpa任务时,at的对象没有直接跟在内容里面</b>
  52.      * </pre>
  53.      *
  54.      * @param msgContent 味精内容
  55.      * @return {@link String}
  56.      */
  57.     private String getShaContentsOfTrimAt(final String msgContent){
  58.         if (msgContent.contains(CommonConstant.SYMBOL_OF_AT)) {
  59.             int i = msgContent.indexOf(CommonConstant.SYMBOL_OF_AT);
  60.             if (i>0) {
  61.                 String trimAtString = msgContent.substring(0, i);
  62.                 return messageContextUtil.getSHAStr(trimAtString);
  63.             }
  64.         }
  65.         String sign =  messageContextUtil.getSHAStr(msgContent);
  66.         log.info("msgContent:{},sign:{}",msgContent,sign);
  67.         return sign;
  68.     }
  69.     /**
  70.      * 通知操作
  71.      *
  72.      * @param taskDetailInfo 任务详细信息
  73.      */
  74.     private void syncNotifyListener(TaskMsgDetailDto taskDetailInfo){
  75.         log.info("通知rpa消息接收结果");
  76.         NotifyTaskRequest request = new NotifyTaskRequest();
  77.         request.setTaskId(String.valueOf(taskDetailInfo.getTaskId()));
  78.         request.setMsgStatus(RpaTaskEnum.RpaMsgStatus.RECEIVE_SUCCESS.getStatus());
  79.         request.setReceivedMsgTime(DateUtil.formatYmdHms(DateUtil.secondToLocalDate(taskDetailInfo.getMsgTime())));
  80.         sendTaskClient.notifyReceivedMessageResult(Arrays.asList(request));
  81.     }
  82. }
复制代码
调用的地方是这样的:⟱⟱⟱

不同状态的处理逻辑

这里抽象层用的是抽象类

使用的时候是通过枚举指定的类型从IOC容器中获取对应的处理实例的,如下⬇︎⬇︎⬇︎

选择使用

使用很灵活,理念很简单。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

来自云龙湖轮廓分明的月亮

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表