zoukankan      html  css  js  c++  java
  • 基于SmartQQ协议的QQ聊天机器人-4

    本节的主题是:结合上节的分析,具体分析函数的实现

    1. 回复消息模块:

    1. 集中在org.b3log.xiaov.service包。主控文件是QQService.java,其他只是回复算法的api和一些支持工具utils,不用管。目前我在研究怎么改写它——支持“基于文本的一问一答”

    2. 配置文件有两个目前用得上:
      src/main/resources下面的xiaov.properties(针对机器人功能做的一些配置);
      log4j.properties(定制整个项目中的Logger模块在各个文件中的级别,用于调试和写日志)

    3. xiaov.properties中设置了bot.follow.keywords和bot.follow.keywordAnswer,就是【捕获关键字】+【返回对应答案魔板】,但是它只是个demo,我要让他支持海量文本,并结构化输入和结构化输出。更多参数的解释见我的代码注释。

    2. 下面针对上述3点进行操作:

    1. 发送消息与回复消息的调用关系:{结合viso绘制调用流程图}
    2. 见代码的修改
    3. 我修改了两个函数:
    • answer里面回复的逻辑+解决编码问题+try-catch;
    • QQService.java里面的onQQGroupMessage对问题的验证逻辑
    /*
    // answer里面回复的逻辑+解决编码问题+try-catch;
    // xiaov_1_0srcmainjavaorg3logxiaovserviceQQService.java
         * 这是我对xiaov-1.0的注释1.0
         * 这个函数非常重要,定义了提问和回答这两个功能的数据结构及数据来源
         * 我会抽时间把这个函数讲清楚 TODO
         * */
    
        private String answer(final String content, final String userName) throws SQLException {
            if (keywords.size() == 0) // 加载一次即可
            {
                // 获取keys,只调用一次
                keywords = AnswersFromSQLite.getAllKeys();
            }
            // LOGGER.debug(keywords.get(0));// 测试下content
            
            String keyword = "";
            for (final String kw : keywords) {
                if (StringUtils.containsIgnoreCase(content, kw)) {
                    keyword = kw;
                    break;
                }
            }
            
           // LOGGER.debug(content);// 测试下content
           // LOGGER.debug(keyword);// 测试下keyword有没有捕捉到
    
            String ret = "";
            String msg = replaceBotName(content);
            if (StringUtils.isNotBlank(keyword)) {
                try { // 这部分是我的改写
                    ret = AnswersFromSQLite.getValue(keyword);// 自定义回复消息
                	ret= URLEncoder.encode(ret, "UTF-8");
                } catch (final UnsupportedEncodingException e) {
                    LOGGER.log(Level.ERROR, "Search key encoding failed", e);
                }
            } else if (StringUtils.contains(content, XiaoVs.QQ_BOT_NAME) && StringUtils.isNotBlank(msg)) {
                    ...
                    // 这部分和作者源码一致,省略了
            }
            
            try {
            	ret= URLDecoder.decode(ret, "UTF-8");
            } catch (final UnsupportedEncodingException e) {
                LOGGER.log(Level.ERROR, "ret decoding failed", e);
            }
            return ret;
        }
        
    // E:Software_installMyEclipse15_20_Workcode_backupxiaov_1_0srcmainjavaorg3logxiaovserviceSQLiteAnswersAnswersFromSQLite.class
    public class AnswersFromSQLite {
        ... //见我的源码
    
        public static String getValue(String key) throws SQLException {
            // 测试查询某条记录
            Dao<t_answers, Integer> dao = getDao();
            List<t_answers> ans = queryByOPtions(dao, key);
            // logger.info(ans.get(0).getValue());
            if (ans != null) {
                return ans.get(0).getValue(); // 仅返回第一条记录的value字段
            }
            return null;
        }
        ... //省略,见我的代码
    }
    
    /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------*/
    
    // QQService.java里面的onQQGroupMessage对问题的验证逻辑
    // E:Software_installMyEclipse15_20_Workcode_backupxiaov_1_0srcmainjavaorg3logxiaovserviceQQService.java
    /*
         * 这是我的注释1.0
         * 这个函数非常重要,我会抽时间把这个函数讲清楚 TODO
         * */
    
        private void onQQGroupMessage(final GroupMessage message) throws SQLException {
            final long groupId = message.getGroupId();
            final long userId = message.getUserId();// 获取消息的sender的QQ号,与机器人的QQ做比较
            //LOGGER.debug(Long.toString(userId));
            //final long botId = XiaoVs.getInt("qq.bot.id");//从配置文件中读当前机器人的QQ号 {还有点bug,后面再修}
            
            // 为了解决2872995315溢出的问题,只能把userId和机器人ID比较由 Long比较   转化成  字符串比较
            String s_userId = Long.toString(userId);
            //final String s_botId = "2872995315";//暂时写死
            final String s_botId = XiaoVs.getString("qq.bot.id"); //从xiaov.properties配置文件中读
    
            final String content = message.getContent();
            final String userName = Long.toHexString(message.getUserId());
            // Push to third system
            String qqMsg = content.replaceAll("\["face",[0-9]+\]", "");
            if (StringUtils.isNotBlank(qqMsg)) {
                qqMsg = "<p>" + qqMsg + "</p>";
                sendToThird(qqMsg, userName);
            }
    
            String msg = "";
            // 下面是对于QQ用户提问的语句进行合法性分析,如果符合规则,那就收集答案,并发送到QQ群 {要避免机器人自问自答的情况发生}
            /*
            if (StringUtils.contains(content, XiaoVs.QQ_BOT_NAME)
                    || (StringUtils.length(content) > 6
                    && (StringUtils.contains(content, "?") || StringUtils.contains(content, "?") || StringUtils.contains(content, "问")))) {
                msg = answer(content, userName);
            }*/
            if ( StringUtils.contains(content, XiaoVs.QQ_BOT_NAME) // TODO:这里是对提问的基本要求{过滤不合法的提问}
                 || (StringUtils.length(content) > 0) && !(s_userId.equals(s_botId))  ) { //彻底解决了机器人自问自答的bug
                msg = answer(content, userName);
            }
            
            if (StringUtils.isBlank(msg)) {
                return;
            }
    
            if (RandomUtils.nextFloat() >= 0.9) {
                Long latestAdTime = GROUP_AD_TIME.get(groupId);
                if (null == latestAdTime) {
                    latestAdTime = 0L;
                }
    
                final long now = System.currentTimeMillis();
    
                if (now - latestAdTime > 1000 * 60 * 30) {
                    msg = msg + "。
    " + ADS.get(RandomUtils.nextInt(ADS.size()));
    
                    GROUP_AD_TIME.put(groupId, now);
                }
            }
            sendMessageToGroup(groupId, msg);
        }
    
    • 我觉得必须要放到svn或者git托管了,否则一旦出错了,没有回滚项目就完了

    3. 突然发现的小Tips:

    突然发现,其实还有个小薇的守护QQ(在哪里有写?防止丢消息??)但是我目前没用守护QQ,依旧正常运行,后面有需要再处理这个tips

  • 相关阅读:
    .NET开源B2C商城项目AssionShop开始开发设计(发布3小时撤下)
    AssionShop开源B2C电子商务系统概述
    ASP.NET中在不同的子域中共享Session
    单元测试框架"艾信.NET单元测试工具(AssionUnit)"开发第二步
    asp.net mvc 分页控件 MvcPager修改;使用范围增大
    Linux服务器测试网络连通性
    如何使用python连接mysql数据库
    mysql数据库基础知识
    使用python创建数据库并插入数据
    Linux下查看日志用到的常用命令
  • 原文地址:https://www.cnblogs.com/LS1314/p/9040465.html
Copyright © 2011-2022 走看看