开发Hubot聊天机器人

大家所熟知的智能聊天机器人,比如:微软小冰、Apple Siri、Google Now、IBM Watson等。微信自动回复、微信服务号里的客服Bot也都算是简单的实例。聊天机器人(Dialog System)主要实现方式有:基于人工模板(比如AIML)、基于搜索技术(比如ElasticSearch)、基于深度学习。从零实现这样的系统是很复杂的。

开源的ChatOps机器人:
1.Hubot:CoffeeScipt编写
2.Lita:Ruby编写
3.Errbot:Python编写

So, What is ChatOps? And How do I Get Started?
12+ Frameworks to Build ChatOps Bots

Hubot是由Github开发的开源聊天机器人,基于Node.js采用CoffeeScript编写。
Hubot https://hubot.github.com/
Hubot Scripts https://github.com/hubot-scripts
Hubot Control https://github.com/spajus/hubot-control

可以借助Hubot开发Chatbot来自动化的完成想要一切自动化任务,比如:
-运维自动化(编译部署代码、重启机器,监控服务器运行情况,自动修复Bug等)
-外部服务交互(管理Redmine、集成Jenkins、监视Zabbix等)
-定时获取天气预报
-随机订餐
-聊天机器人等等。

官方文档里有详细的使用说明,https://hubot.github.com/docs/,这里只做一个摘要。
Hubot Scripts里有大量的现成脚本可以用,也是自己编写脚本的最好sample。

(一)安装
运行Hubot需要以下软件支持:

  • Node.js
  • Redis 默认存贮数据
  • CoffeeScript
  • Yeoman
  • generator-hubot 生成Hubot骨架工程

 

引用
C:\Users\rensanning>node -v
v0.12.8
C:\Users\rensanning>npm -v
2.14.9
C:\Users\rensanning>npm install -g yo generator-hubot
C:\Users\rensanning>npm list -g generator-hubot yo

(二)创建自己的bot

引用
C:\Users\rensanning>cd d:/
D:\>mkdir hubotsample
D:\>cd hubotsample
D:\hubotsample>yo hubot
? Owner RenSanNing <rensanning@gmail.com>
? Bot name okbot
? Description A sample hubot
? Bot adapter campfire

默认提供了campfire和shell的adapter,其他的需要通过npm下载hubot-<AdapterName>。
也可以通过参数直接生成:

引用
yo hubot –owner=rensanning@gmail.com –name=foobot –description=”Foo Bot” –adapter=shell

项目结构:

  • bin/ 运行脚本
  • node_modules 应用的包文件
  • scripts 存放自定义脚本
  • external-scripts.json 应用的外部脚本
  • hubot-scripts.json *** 该文件已经无用,可以删除
  • package.json 项目全局配置信息

(三)运行bot

引用
D:\hubotsample>bin\hubot -v
2.19.0
D:\hubotsample>bin\hubot -h
Usage hubot [options]

Available options:
-a, –adapter ADAPTER   The Adapter to use
-c, –create PATH       Create a deployable hubot
-d, –disable-httpd     Disable the HTTP server
-h, –help              Display the help information
-l, –alias ALIAS       Enable replacing the robot’s name with alias
-n, –name NAME         The name of the robot in chat
-r, –require PATH      Alternative scripts path
-t, –config-check      Test hubot’s config to make sure it won’t fail at startup
-v, –version           Displays the version of hubot installed

-a 指定Adapter(默认是shell)
-d 关闭HTTP服务(默认是开启的)
-c deprecated 使用yeoman

采用默认的shell adapter

引用
D:\hubotsample>bin\hubot

指定adapter

引用
D:\hubotsample>bin\hubot -a shell

 

引用
okbot> help
usage:
history
exit, \q – close shell and exit
help, \? – print this usage
clear, \c – clear the terminal screen

 

引用
okbot> okbot help
okbot> Shell: okbot adapter – Reply with the adapter
okbot animate me <query> – The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead.
okbot echo <text> – Reply back with <text>
okbot help – Displays all of the help commands that Hubot knows about.
okbot help <query> – Displays all help commands that match <query>.
okbot image me <query> – The Original. Queries Google Images for <query> and returns a random top result.
okbot map me <query> – Returns a map view of the area returned by `query`.
okbot mustache me <url|query> – Adds a mustache to the specified URL or query result.
okbot ping – Reply with pong
okbot pug bomb N – get N pugs
okbot pug me – Receive a pug
okbot the rules – Make sure hubot still knows the rules.
okbot time – Reply with current time
okbot translate me <phrase> – Searches for a translation for the <phrase> and then prints that bad boy out.
okbot translate me from <source> into <target> <phrase> – Translates <phrase> from <source> into <target>. Both <source> and <target> are optional
ship it – Display a motivation squirrel

okbot ping
okbot> PONG

okbot echo 你好!
okbot> 你好!

okbot time
okbot> Server time is: Fri Sep 30 2016 11:05:24 GMT+0800 (中国 (标准时间))

***所有的输入都会被记录在.hubot_history文件里。

(四)编写脚本
编写的自定义脚本要放在scripts中,可以是.coffee或.js文件。

scripts/hello.coffee

Js代码  收藏代码
  1. # Description:
  2. #   This is a test.
  3. #
  4. # Commands:
  5. #   okbot helo – Reply with world!
  6. module.exports = (robot) ->
  7.   robot.respond /hello/i, (msg) ->
  8.     msg.send “world!”

 

引用
okbot hello
okbot> world!

因为Hubot要解析脚本文件,提供help帮助,所以脚本文件开头的注释是规范的,
第一行必须是注释“# Description:”(其他的可以没有),否则会有警告:

引用
hello.coffee is using deprecated documentation syntax

Hubot同时也支持js,比如:
scripts/hello2.js

Js代码  收藏代码
  1. // Description:
  2. //   This is a test2.
  3. // Commands:
  4. //   okbot helo – Reply with world!
  5. module.exports = function(robot) {
  6.     robot.respond(/hi/i, function(msg){
  7.         msg.send(“world2!”);
  8.     });
  9. }

 

引用
okbot hi
okbot> world2!

Respond vs Hear

  • respond只监听直接发送给机器人的消息,需要指定机器人名称
  • hear可以监听任何消息

 

引用
MYHUBOT xxx
myhubot xxx
@myhubot xxx
myhubot: xxx

Send vs Reply

  • send会将消息发送给所有人
  • reply会将消息回复给指定的人

Random
msg对象有一个random方法,可以从之后的数组对象中随机提取一个元素

引用
msg.send msg.random arrayObject

hubot Scripts Explained
http://theprogrammingbutler.com/blog/archives/2011/10/28/hubot-scripts-explained/

(五)安装脚本
Hubot 有一大堆现成的脚本,可以集成各种服务。

引用
D:\hubotsample>npm search hubot-scripts github
D:\hubotsample>npm install –save hubot-plusplus
hubot-plusplus@1.3.0 node_modules\hubot-plusplus
├── underscore@1.8.3
├── clark@0.0.6
└── coffee-script@1.6.3

将package-name添加到external-scripts.json

引用
“hubot-plusplus”

 

引用
okbot> ruby++
okbot> ruby has 1 point
okbot> java–
okbot> java has -1 points

(六)hubot-script实例

定时脚本
scripts/cron.coffee

Js代码  收藏代码
  1. cronJob = require(‘cron’).CronJob
  2. module.exports = (robot) ->
  3.   send = (room, msg) ->
  4.     response = new robot.Response(robot, {user : {id : -1, name : room}, text : “none”, done : false}, [])
  5.     response.send msg
  6.   new cronJob(‘0 * * * * *’, () ->
  7.     currentTime = new Date
  8.     send ‘#your-channel-name’“current time is #{currentTime.getHours()}:#{currentTime.getMinutes()}.”
  9.   ).start()

 

引用
D:\hubotsample>npm install cron –save
D:\hubotsample>bin\hubot -a shell

http请求
scripts/googleGEO.coffee

Js代码  收藏代码
  1. module.exports = (robot) ->
  2.   robot.hear /location (.*)/, (msg) ->
  3.     request = robot.http(“https://maps.googleapis.com/maps/api/geocode/json”)
  4.                    .query(address: msg.match[1])
  5.                    .get()
  6.     request (err, res, body) ->
  7.       json = JSON.parse body
  8.       location = json[‘results’][0][‘geometry’][‘location’]
  9.       msg.send “#{location[‘lat’]}, #{location[‘lng’]}”

 

引用
okbot> location Beijing
okbot> 39.904211, 116.407395

抓取数据(request, cheerio)
scripts/title.coffee

Js代码  收藏代码
  1. request = require ‘request’
  2. cheerio = require ‘cheerio’
  3. module.exports = (robot) ->
  4.   robot.respond /title (.*)/i, (msg) ->
  5.     url = msg.match[1]
  6.     options =
  7.       url: url
  8.       timeout: 2000
  9.       headers: {‘user-agent’‘node title fetcher’}
  10.     request options, (error, response, body) ->
  11.       $ = cheerio.load body
  12.       title = $(‘title’).text().replace(/\n/g, )
  13.       msg.send(title)

 

引用
D:\hubotsample>npm install –save request
D:\hubotsample>npm install –save cheerio
D:\hubotsample>bin\hubot -a shell

okbot> okbot title http://github.com
okbot> How people build software · GitHub
okbot> okbot title http://www.google.com
okbot> Google

http应答(httpd)
scripts/version.coffee

Js代码  收藏代码
  1. module.exports = (robot) ->
  2.   robot.router.get “/version”, (req, res) ->
  3.     res.end robot.version

访问http://localhost:8080/version。
默认端口是8080,可以修改环境变量:export PORT=8080

Hubot大量依赖环境变量来配置脚本,所以一般都做一个启动脚本:

引用
#!/bin/sh
export HUBOT_ENV_TEST_VAR=””
bin/hubot -a twitter -n testbot

 

引用
@echo off
SET HUBOT_ENV_TEST_VAR=””
bin\hubot.cmd -a twitter -n testbot

脚本中的使用:

引用
TEST_VAR = process.env.HUBOT_ENV_TEST_VAR

捕获所有未处理信息
scripts/catchAll.coffee

Js代码  收藏代码
  1. module.exports = (robot) ->
  2.   robot.catchAll (res) ->
  3.     res.send “Nothing Found:#{res.message.text}”

hubotスクリプトの書き方とサンプル集
http://blog.fumiz.me/2012/08/05/hubot-irc-bot-script/
编写 Hubot Scripts
http://scarletsky.github.io/2016/05/02/write-your-own-hubot-scripts/

(七)自定义Adapter
hubot默认提供两种adapter:shell、campfile
shell用于开发调试,campfile以外的Chat Service也都有开源的实现。

Adapter基本构成

新建文件 \node_modules\hubot\src\adapters\SampleAdapter.coffee

Js代码  收藏代码
  1. class SampleAdapter extends Adapter
  2.   send: (envelope, strings…) ->
  3.     @robot.logger.info “Send”
  4.   run: ->
  5.     @robot.logger.info “Run”
  6. exports.use = (robot) ->
  7.   new SampleAdapter robot

修改文件 \node_modules\hubot\src\robot.coffee

引用
HUBOT_DEFAULT_ADAPTERS = [
‘campfire’
‘SampleAdapter’
‘shell’
]

启动bot

引用
D:\hubotsample>bin\hubot -a SampleAdapter

* 所有的Adapter必须继承自Adapter
* Adapter中最重要的两个方法是send和run,其他方法比如emote、reply、topic、play等在特定场景下才需要。
* run方法是bot启动时执行
* send方法是回复信息时执行
* 父类 adapter.coffee 里有详细的方法说明 https://github.com/github/hubot/blob/master/src/adapter.coffee
* Adapter名必须是:src\adapters里的文件名 & robot.coffee的HUBOT_DEFAULT_ADAPTERS里定义的名 或者和 hubot-#{adapter} 一致

Chat服务的Adapter

Js代码  收藏代码
  1. {Adapter, TextMessage} = require ‘hubot’
  2. {EventEmitter} = require ‘events’
  3. class MyChatAdapter extends Adapter
  4.   send: (envelope, strings…) ->
  5.     @bot.send str for str in strings
  6.   run: ->
  7.     options =
  8.       token:   process.env.HUBOT_CHAT_TOKEN
  9.       rooms:   process.env.HUBOT_CHAT_ROOMS
  10.       account: process.env.HUBOT_CHAT_ACCOUNT
  11.     bot = new MyChatStreaming options, @robot
  12.     bot.on ‘message’, (userId, userData, message) ->
  13.       user = @robot.brain.userForId userId, userData
  14.       @receive new TextMessage user, message
  15.     bot.listen()
  16. exports.use = (robot) ->
  17.   new MyChatAdapter robot
  18. class MyChatStreaming extends EventEmitter
  19.   constructor: (options, @robot) ->
  20.     @token         = options.token
  21.     @rooms         = options.rooms.split(“,”)
  22.     @account       = options.account
  23.   send: (message) ->
  24.     # Send data to your chat service
  25.   listen: ->
  26.     # Get messge data from chat service
  27.     # @emit ‘message’, user, message

具体可以参考: https://github.com/github/hubot/blob/master/src/adapters/campfire.coffee

扩展robot的方法:
\node_modules\hubot\src\adapters\incircle.coffee

Java代码  收藏代码
  1. class TestXXX extends Adapter
  2.   constructor: (robot) ->
  3.     super robot
  4.     robot.hearXXX = (options, callback) ->
  5.       robot.listeners.push new TextListener(robot, “@XXXmessage”, options, callback)

\scripts\testbot.coffee

Java代码  收藏代码
  1. module.exports = (robot) ->
  2.   robot.hearXXX (msg) ->
  3.     msg.send “#{JSON.stringify msg}”

(八)微信adapter
https://github.com/KasperDeng/Hubot-WeChat

主要机制是hack网页版微信协议,先用手机登录微信帐号,然后模拟网页版微信登录,这样就可以接受微信消息了。

  • npm install hubot-weixin –save
  • 手机端登录微信
  • 打开网页微信:web.weixin.qq.com
  • 手机扫描登录
  • 控制台查看如下信息 /node_modules/hubot-weixin/config.yaml
  • cookie: Uin: Sid: Skey: DeviceID:

  • bin\hubot.cmd -n bot -l / -a weixin

参考:
正在吃掉世界的Bot:它从哪里来,会到哪里去?
Hubot:来自GitHub的聊天机器人
GitHub社謹製! bot開発・実行フレームワーク「Hubot」
TDD Hubot scripts with gulp+mocha
在Skype中使用Hubot
http://qiita.com/bouzuya/items/c7d0ad80c357aab6b696

Share