2019独角兽企业重金招聘Python工程师标准>>>

前言

每次写前言最费神,就是感兴趣想研究研究,有了一点点成果希望分享交流,如果能帮助别人就很好,如果有人指导一下就更好了。这次是关于'微信机器人'的个人设计。

功能简介

现在的功能比较简陋,仅实现了聊天机器人(基于图灵机器人API) 和 定时提醒功能(可以实现按时点/周期定制)。但是整体构架是设计出来了,进行扩展 应该 还是挺方便的。放几张图作示例。

登陆部署程序的端口,用个人微信扫码登陆(注意:请先确认微信账号是否能正常登陆wx.qq.com) 扫码后,通过另一个账号发送 召唤智障机器人 激活。大致聊天情况如下 因为功能还不稳定,所以就不挂我自己的程序了。如果稳定了再挂

依赖介绍

  • JDK8
  • Springboot2,最近使用Springboot习惯,写起来顺手,同时希望能部署在服务器上长期运行,所以设计成web服务管理。
  • itchat4j 开源的基于微信web协议开发的个人微信号扩展接口的java实现。免除了自己去研究微信web,感谢。为了符合项目需求,做了一点微小的改动,jar包在源码的libs文件夹下
  • mysql,实现一些数据持久化功能。主要原因在于微信web是有登陆时限的,同时升级程序重启时希望能恢复定时任务、保留用户关联信息等。
  • 图灵机器人API 需要自己申请一个apikey。免费版聊天真的很智障( ╯╰ )

整体设计思路

itchat4j 提供了 Wechat 主类作为入口程序,需要注入一个实现IMsgHandlerFace接口的实现类作为接收消息的回调。这方面我自己完成一个CentreMessageHandler,目前只处理text消息。

    @Overridepublic String textMsgHandle(BaseMsg baseMsg) {// processorManager处理器的管理类BaseProcessor filter = processorManager.decision(baseMsg);if (filter != null && filter instanceof TextProcessor) {TextProcessor processor = (TextProcessor)filter;try {return processor.answer(baseMsg);}catch (AnswerException e) {logger.error("An answerException happened", e);return  "我的爸爸写了个bug,可能是缺少女朋友导致,要关心一下吗";}}return null;}

我希望程序能更智能,针对不同的输入响应不同的内容,而逻辑不可能都写在一个方法里。所以我学习了一下SpringSecury的Filter链设计,设计了一个Processor链。Processor需要实现我定义的一个接口处理程序

/*** 处理器接口, 定义decide用于指示处理器是否响应消息** 提供默认的process方法, 用于提供在 {@link Decision} 响应PROCESS时处理消息* @author BekeyChao@github.com*/
public interface BaseProcessor {Logger logger = LoggerFactory.getLogger(BaseProcessor.class);/*** 是否处理消息* @param message* @return {@link Decision} 按需返回你的决定*/Decision decide(BaseMsg message);/*** 处理消息,但不会打断消息的传播* @param message*/default void process(BaseMsg message) {if ( logger.isDebugEnabled() ) {logger.debug("你请求处理了一个消息, 但是却没有实现 class = " + this.getClass().getName());}// ignore}enum Decision {/*** 处理并结束流程*/ACCEPT,/*** 调用process方法处理消息但不结束流程*/PROCESS,/*** 不处理但不结束流程*/PASS,/*** 拒绝并结束流程*/DENY;}
}

这个接口核心在于decide方法,decide的返回值决定了消息的处理逻辑,详见enum Decision。BaseProcessor 在ProcessorManager中其实就是一段ArrayList,按预定义好的Processor顺序决定哪个Processor可以获得处理权限,manager的实现是这样的

    /*** 决定使用哪个处理组件进行处理* @param message* @return null 代表不响应*/public BaseProcessor decision(BaseMsg message) {for (BaseProcessor filter: processors) {switch (filter.decide(message)) {case ACCEPT:return filter;case PROCESS:filter.process(message);continue;case DENY:return null;default:// pass}}return null;}

我一共设计了5个Processor,执行顺序

  • CommandTextProcessor 强指令响应器, 用于响应固定系统基本指令, 如开启机器人, 关闭机器人等
  • UserFilter 服务响应过滤器, 可以用于指定服务于特定用户
  • ContextService 上下文管理响应器,用于响应连续的对话内容
  • ScheduleProcessor 行程提醒处理器 响应定制提醒及提醒取消
  • TuringTextProcessor 图灵机器人响应器, 调用图灵机器人接口与用户聊天响应 manager中开放了管理Processor的接口,所以可以实现自己的处理逻辑,进行扩展。

如果对Processor具体逻辑感兴趣可以到源码中看,这里我主要介绍一下ContextService 上下文响应处理器。因为我希望程序聊天是可以有情景的,机器人可以响应一段连续的对话,所以额外设计了一个SceneContext的概念。ContextService 的decide方法就是检查用户是否有场景值,场景值是由其他处理器创建的(在本例中,都是由ScheduleProcessor创建的)。SceneContextHolder用于储存场景值。

    @Overridepublic Decision decide(BaseMsg message) {// 用户场景值有消息if ( SceneContextHolder.getArgumentsByUserId(message.getFromUserName()) != null) {return Decision.ACCEPT;}return Decision.PASS;}

场景是一段预定义的响应,act是执行方法

/*** 场景信息接口* @author BekeyChao@github.com*/
public interface BaseSceneContext {// 定义场景Id,保证程序级别的唯一String sceneId();String act(String userId, BaseMsg message);/*** 定义是否在响应后自动移除场景值,默认true* @return true 自动移除*/default boolean isRemovedAfterResponse() {return true;}/*** 定义会话过期时间 毫秒值 未实现* @return -1 永不过期*/long express();
}

那么我如何知道用户的场景呢?这是一段约定,在ScheduleProcessor行程提醒处理器中,用户消息达成了它的要求时,它会根据消息往SceneContextHolder中置入场景

BaseSceneContext context = SceneContextHolder.getSceneBySceneId('定义的场景Id');
// Arguments是场景参数,约定args[0] 存储场景
SceneContextHolder.setArgumentsByUserId(message.getFromUserName(), new Object[]{ context });

这样ContextService就可以通过用户Id拿到场景并执行。 在ChatrobotConfig中会扫描bean,将实现BaseSceneContext的实现类都放到SceneContextHolder中,所以在程序中想新增场景就直接实现BaseSceneContext接口就可以了。

嗯,核心想分享的思路就到这里了,其他的具体实现可以看看源码。我觉得我的程序设计比较繁琐,但是保留了比较好的扩展性,因为也是自己第一次做比较完整的程序设计,所以想分享一下。如果由大佬恰巧看到,愿意指导一下也是极好的。

整个程序目前只能算半成品,修修补补的地方很多。我本想做的差不多再分享一下,不过感觉任重道远,所以提前献丑。

源码传送门

chatrobot

git 关联时少同步了application.properties,主要保存了我私有的key,需要补充完整才能启动

spring.datasource.url =
spring.datasource.username =
spring.datasource.password = chatrobot.turing.key = 在图灵API申请的key

存在的已知问题

  • 程序重启时应从数据库中加载任务,暂时没有实现
  • 用户实体关联还没有建立
  • 收到消息时,都会收到一个fromUserId的属性,程序主要靠这个实现指定收发消息。但根据测试,这个id对用户而言并不是固定的!就是每次重新登陆后好友的UserId会变,需要设计一个方法实现唯一用户关联(nickname可能重复)
  • 服务器部署在外网可能会有异常退出。我第一次对外测试的时候部署在aws上,但是半个多小时后莫名挂了。

Futrue

  • 实现定时任务在启动时加载。
  • 将用户也放入Mysql中进行管理。
  • 其他想到什么写什么

希望多多交流

如果有更好的设计思路,希望能分享一下,Thanks!

转载于:https://my.oschina.net/u/3491123/blog/1807004

我的微信'智障聊天助手'的设计思路相关推荐

  1. 从零开始造一个“智障”聊天机器人

    腾讯DeepOcean原创文章:dopro.io/nlp_seq2seq- 智能机器人在生活中随处可见:iPhone里会说话的siri.会下棋的阿法狗.调皮可爱的微软小冰--她们都具有一定的智能,能够 ...

  2. 用机器学习拯救“智障”聊天机器人,谷歌开放分析平台Chatbase

    李杉 李林 编译整理 量子位 出品 | 公众号 QbitAI 当你做了一个网站.App.游戏,肯定会马上想到要加上统计分析功能,这早就成了互联网产品的标配组件,产品迭代.用户运营,都离不开它. 如果你 ...

  3. 用30行代码做一个微信智障机器人

    起因是某天早上看到这样一条朋友圈: 微信啥时候还有会员了?可怕,花里胡哨,这是要往QQ的方向发展吗.还是 Telegram 比较存粹. 连IS恐怖组织都在使用,最安全的即时通讯软件--Telegram ...

  4. 局域网聊天软件的设计思路

    遗憾的 局域网聊天软件 是,那时我们都把这个当成一个joke,充其量回复一句i服了you!,而没有反思使用标准算法的问题.目前来看,在口令保存上,使用最为广泛的算法是标准md5 hash.但实际上,很 ...

  5. 轻聊 - 聊天室的设计思路

    1.写在前面 学完Java后,一方面为了巩固知识,另一方面也是看看自己对知识的掌握程度,所以动手写了一个小型Java项目 - 简易聊天室.它是一个可以实现多人通讯功能的简单项目.因为是第一次自己写项目 ...

  6. 优质微信小程序的体验与设计思路

    体验和设计评估 在小程序的设计和开发阶段,我们希望开发者始终将优秀的用户体验作为产品目标之一,通过积极的用户体验和设计评估,在不断的迭代中完善用户体验,用心打磨小程序,从而更好实现产品价值,激发用户正 ...

  7. 中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障------07

    中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障------07 - 浩海泛舟的文章 - 知乎 https://zhuanlan.zhihu.com/p/51771041 ...

  8. 中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障------05

    中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障------05 - 浩海泛舟的文章 - 知乎 https://zhuanlan.zhihu.com/p/51276692 ...

  9. 中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障---08

    中文编程,最精致的python访客登记系统实例项目,微信机器人不再只当人工智障---08 - 浩海泛舟的文章 - 知乎 https://zhuanlan.zhihu.com/p/51902838 面向 ...

最新文章

  1. 现在的路由器是第几代了?每一代的特点是?
  2. openssl简介-指令s_client
  3. 小程序如何实现tab切换,一部到位
  4. java循环 排序 查找
  5. 我年龄大了还学的动it吗
  6. getconnection java_在MyEclipse用java写的一个GetConnection1.java,用于连接MySQL,却总是出错。(没有财富值了,见谅!)...
  7. 计算机算法设计与分析 矩阵连乘问题
  8. Element Form表单布局(一行多列)
  9. JAVA – 虚函数、抽象函数、抽象类、接口_对比C++
  10. 输入正方体的边长,计算正方体的面积和体积
  11. 帕累托分布(Pareto distributions)、马太效应
  12. MATLAB求积分函数int
  13. webview 禁止苹果自动下拉_苹果开发者账号申请必备:双重认证教程!
  14. 美团App用户界面分析
  15. termite:从零开始的go语言学习生活
  16. Microsoft Visio Professional 2013打不开也卸载不了解决办法
  17. python爬虫设计模式_Python爬虫进阶一之爬虫框架概述
  18. C#软件开发实例.私人订制自己的屏幕截图工具——放大镜的功能代码优化
  19. 西安科技大学计算机院,计算中心-西安科技大学计算机科学与技术学院
  20. 线下商店如何转型做新零售 怎么样顺利开展新零售模式?

热门文章

  1. 如何使用Hololens 这些手势你都要学
  2. arcgis andin使用python窗体_在ArcGIS?10中使用python
  3. 只用一张图+相机走位,AI就能脑补周围环境,来自华人团队 | CVPR2022
  4. AI学高数达到MIT本科水平,学了微积分线性代数概率论等6门课,不光能做题还能出题...
  5. 刚盈利的DeepMind收购MuJoCo:转手开源,所有人免费用
  6. 塑料:泡两天澡我就消失了?酶降解塑料居然可以这么快 | Nature
  7. 免息月供137元,新iPhone SE有7大理由值得买!但反对只需这1个就够了
  8. 华人科学家在加拿大被区别对待,曾研究出埃博拉病毒治疗方法,Science刊文:同行震惊...
  9. mormot支持websocket
  10. Linux文件实时同步--inotify + rsync + pyinotify