bilingfeng 1 год назад
Родитель
Сommit
2fa698b3a7

+ 1 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java

@@ -23,7 +23,7 @@ public class ManageApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ManageApplication.class, args);
-        System.out.println("赞象Manage服务启动成功 <调试修改10> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 <客服系统新增关键词监测> ( ´・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

+ 9 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameAuthRoleService.java

@@ -17,6 +17,15 @@ import java.util.Map;
  */
 public interface IGameAuthRoleService extends IService<GameAuthRole> {
 
+    /**
+     * 给游戏客服发送消息
+     *
+     * @param gameId   : 游戏id
+     * @param gameName : 游戏名称
+     * @param msg      : 消息
+     */
+    void dingTalkCustomer(Long gameId, String gameName, String msg);
+
     /**
      * 是否是客服
      *

+ 12 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfMonitorWordService.java

@@ -0,0 +1,12 @@
+package com.zanxiang.game.module.manage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.mybatis.entity.KfMonitorWord;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-12
+ * @description : 监测词汇
+ */
+public interface IKfMonitorWordService extends IService<KfMonitorWord> {
+}

+ 40 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameAuthRoleServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.erp.base.ErpServer;
+import com.zanxiang.erp.base.rpc.IDingTalkMsgRpc;
 import com.zanxiang.erp.base.rpc.ISysUserRpc;
 import com.zanxiang.erp.security.util.SecurityUtil;
 import com.zanxiang.game.module.base.pojo.enums.DeleteEnum;
@@ -44,9 +45,48 @@ public class GameAuthRoleServiceImpl extends ServiceImpl<GameAuthRoleMapper, Gam
     @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
     private ISysUserRpc sysUserRpc;
 
+    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
+    private IDingTalkMsgRpc dingTalkMsgRpc;
+
     @Autowired
     private IGameAuthService gameAuthService;
 
+    @Override
+    public void dingTalkCustomer(Long gameId, String gameName, String msg) {
+        Set<Long> customerIdSet = super.list(new LambdaQueryWrapper<GameAuthRole>()
+                .eq(GameAuthRole::getAuthType, GameAuthEnum.CUSTOMER.getValue())
+        ).stream().map(GameAuthRole::getUserId).collect(Collectors.toSet());
+        if (CollectionUtils.isEmpty(customerIdSet)) {
+            return;
+        }
+        Set<Long> gameCustomerIdSet = gameAuthService.list(new LambdaQueryWrapper<GameAuth>()
+                .eq(GameAuth::getGameId, gameId)
+                .in(GameAuth::getUserId, customerIdSet)
+        ).stream().map(GameAuth::getUserId).collect(Collectors.toSet());
+        if (CollectionUtils.isEmpty(gameCustomerIdSet)) {
+            return;
+        }
+        gameCustomerIdSet.forEach(customerId -> {
+            try {
+                dingTalkMsgRpc.sendByUserId(customerId, msgStr(gameName, msg));
+            } catch (Exception ignored) {
+            }
+        });
+    }
+
+    private String msgStr(String gameName, String msg) {
+        return "客服系统关键词监测: " +
+                "\n" +
+                "时间: " +
+                LocalDateTime.now() +
+                "\n" +
+                "游戏名称: " +
+                gameName +
+                "\n" +
+                "玩家发送内容: " +
+                msg;
+    }
+
     @Override
     public boolean isCustomer() {
         return super.count(new LambdaQueryWrapper<GameAuthRole>()

+ 23 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java

@@ -90,6 +90,12 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
     @Autowired
     private IKfSystemReplyService kfSystemReplyService;
 
+    @Autowired
+    private IKfMonitorWordService kfMonitorWordService;
+
+    @Autowired
+    private IGameAuthRoleService gameAuthRoleService;
+
     @Autowired
     private RedisUtil<String> redisUtil;
 
@@ -127,6 +133,8 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
         }
         //客服休息时间, 发送自动回复
         this.systemReplyHandle(gameApplet.getGameId(), kfAppletMsgDTO.getFromUserName(), kfRoom);
+        //消息报警监测
+        this.monitorWordHandle(gameApplet, kfAppletMsgDTO);
         //保存房间消息
         kfRoomMsgService.save(kfRoomMsg);
         //玩家状态更新为待接入状态
@@ -141,6 +149,21 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
         this.pushMessage(this.transform(kfRoom, gameApplet.getGameId(), kfRoomMsg, msgContent));
     }
 
+    private void monitorWordHandle(GameApplet gameApplet, KfAppletMsgDTO kfAppletMsgDTO) {
+        //非文本消息
+        if (!Objects.equals(kfAppletMsgDTO.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue())) {
+            return;
+        }
+        //未匹配导监测词汇
+        if (kfMonitorWordService.count(new LambdaQueryWrapper<KfMonitorWord>()
+                .like(KfMonitorWord::getWord, kfAppletMsgDTO.getContent())
+        ) <= 0) {
+            return;
+        }
+        //给客服发送钉钉通知
+        gameAuthRoleService.dingTalkCustomer(gameApplet.getGameId(), gameApplet.getAppName(), kfAppletMsgDTO.getContent());
+    }
+
     private void systemReplyHandle(Long gameId, String openId, KfRoom kfRoom) {
         //获取自动回复配置
         KfSystemReply kfSystemReply = kfSystemReplyService.getById(gameId);

+ 18 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfMonitorWordServiceImpl.java

@@ -0,0 +1,18 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.manage.service.IKfMonitorWordService;
+import com.zanxiang.game.module.mybatis.entity.KfMonitorWord;
+import com.zanxiang.game.module.mybatis.mapper.KfMonitorWordMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-12
+ * @description : 客服监测词汇
+ */
+@Slf4j
+@Service
+public class KfMonitorWordServiceImpl extends ServiceImpl<KfMonitorWordMapper, KfMonitorWord> implements IKfMonitorWordService {
+}

+ 6 - 3
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java

@@ -327,8 +327,11 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
                 .gameId(gameId)
                 .roomList(onlineRoomList)
                 .build());
-        //释放锁
-        distributedLockComponent.unlock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId());
+        //以防锁依然存在, 尝试释放锁, 锁如果不存在, 会抛出异常, 直接捕获不处理
+        try {
+            distributedLockComponent.unlock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId());
+        } catch (Exception ignored) {
+        }
     }
 
     private void finishRoomList(WebSocketSession session, KfWebSocketMsgParam param) {
@@ -390,7 +393,7 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         }
         //触发玩家接入线程锁
         if (!distributedLockComponent.doLock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId(),
-                0L, 5L, TimeUnit.MINUTES)) {
+                0L, 3L, TimeUnit.MINUTES)) {
             this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家已被其他客服接入"));
             return;
         }