• このエントリーをはてなブックマークに追加


はじめに

今さらながら,bot フレームワークである Hubot を触ってみたのでその記録.

参考

前者の連載 第2回目,「Hubotを動かしてみる」におけるひな形作成あたりの勝手は,現在のものとは異なっているようなので,そのあたりは本家の方を重視.

目次

  1. インストール
  2. ひな形を作成
  3. とりあえず体感: shell アダプタ
  4. ちょこっとだけ拡張してみる
  5. IRC に接続する: irc アダプタ
  6. Slack に接続する: slack アダプタ

インストール

Hubot は node.js 製なので,そのあたりから.

nodebrew

Homebrew であれば:

% brew install nodebrew

で入ります.そうでなければ

% curl -L git.io/nodebrew | perl - setup

した後,$HOME/.nodebrew/current/bin を環境変数 PATH に追加しておきます:

export $HOME/.nodebrew/current/bin:$PATH

node

% nodebrew install v0.10.33
(... takes a while ...)
% nodebrew use v0.10.33

Hubot 関連モジュール

Yeomangenerator-hubot を追加します.基本的なものなのでグローバルなところに:

% npm install -g yo generator-hubot

ひな形を作成

yo hubot した後,聞かれることにテキトーに Enter していけば,bot するためのファイル構成を準備してくれます:

% git init /path/to/myhubot
Initialized empty Git repository in /path/to/myhubot/.git/
% cd /path/to/myhubot
% yo hubot
                     _____________________________
                    /                             \
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             /
 ======= |[^_/\_]|   /----------------------------
  |   | _|___@@__|__
  +===+/  ///     \_\
   | |_\ /// HUBOT/\\
   |___/\//      /  \\
         \      /   +---+
          \____/    |   |
           | //|    +===+
            \//      |xx|
 
? Owner: issm <issm@myemail>
? Bot name: myhubot
? Description: myhubot
? Bot adapter: campfire
   create bin/hubot
   create bin/hubot.cmd
   create Procfile
   create README.md
   create external-scripts.json
   create hubot-scripts.json
   create .gitignore
   create package.json
   create scripts/example.coffee
   create .editorconfig
                     _____________________________
 _____              /                             \
 \    \             |   Self-replication process   |
 |    |    _____    |          complete...         |
 |__\\|   /_____\   \     Good luck with that.    /
   |//+  |[^_/\_]|   /----------------------------
  |   | _|___@@__|__
  +===+/  ///     \_\
   | |_\ /// HUBOT/\\
   |___/\//      /  \\
         \      /   +---+
          \____/    |   |
           | //|    +===+
            \//      |xx|
 
hubot-maps@0.0.0 node_modules/hubot-maps
 
hubot-help@0.1.1 node_modules/hubot-help
 
hubot-google-images@0.1.0 node_modules/hubot-google-images
 
hubot-diagnostics@0.0.1 node_modules/hubot-diagnostics
 
hubot-pugme@0.1.0 node_modules/hubot-pugme
 
hubot-rules@0.1.0 node_modules/hubot-rules
 
hubot-youtube@0.1.2 node_modules/hubot-youtube
 
hubot-google-translate@0.1.0 node_modules/hubot-google-translate
 
hubot-heroku-keepalive@0.0.4 node_modules/hubot-heroku-keepalive
 
hubot-shipit@0.1.1 node_modules/hubot-shipit
 
hubot-redis-brain@0.0.2 node_modules/hubot-redis-brain
└── redis@0.8.4
 
hubot-scripts@2.5.16 node_modules/hubot-scripts
└── redis@0.8.4
 
hubot@2.9.3 node_modules/hubot
├── optparse@1.0.4
├── log@1.4.0
├── scoped-http-client@0.9.8
├── coffee-script@1.6.3
└── express@3.18.1 (basic-auth@1.0.0, merge-descriptors@0.0.2, utils-merge@1.0.0, fresh@0.2.4, cookie@0.1.2, escape-html@1.0.1, range-parser@1.0.2, cookie-signature@1.0.5, vary@1.0.0, media-typer@0.3.0, parseurl@1.3.0, methods@1.1.0, content-disposition@0.5.0, depd@1.0.0, debug@2.1.0, etag@1.5.1, proxy-addr@1.0.3, commander@1.3.2, mkdirp@0.5.0, send@0.10.1, connect@2.27.1)
% git add .
% git commit -m 'initial commit'

とりあえず体感: shell アダプタ

さっそく bin/hubot を実行することで,シェル上でのインタラクティヴを体感できるでしょう(Heroku 云々のエラーが出てますが無視):

ちょこっとだけ拡張してみる

挙動の拡張は,coffeescript で行えるらしいです.個人的に非常にありがたい.

次のようなスクリプト:

# Description:
#   hello
#
# Notes:
#   はろー -> コンニチハ
 
module.exports = (robot) ->
    robot.hear /はろー/, (msg) ->
        msg.reply 'コンニチハ'

を,scripts/hello.coffee として置いた状態で bin/hubot を実行すると,「はろー」の含まれるメッセージに反応して「コンニチハ」を返してくるようになります:

IRC に接続する: irc アダプタ

node モジュール hubot-irc を追加する:

% npm install hubot-irc --save && npm install
npm WARN package.json hubot-maps@0.0.0 No repository field.
hubot-irc@0.2.7 node_modules/hubot-irc
├── log@1.4.0
└── irc@0.3.6 (ansi-color@0.2.1)
npm WARN package.json hubot-maps@0.0.0 No repository field.
% git diff
diff --git a/package.json b/package.json
index d5f1047..a90d37f 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "hubot-google-translate": "^0.1.0",
     "hubot-help": "^0.1.1",
     "hubot-heroku-keepalive": "0.0.4",
+    "hubot-irc": "^0.2.7",
     "hubot-maps": "0.0.0",
     "hubot-pugme": "^0.1.0",
     "hubot-redis-brain": "0.0.2",

起動用シェルスクリプトを準備:

% touch bin/run_irc
% chmod +x bin/run_irc

中身はこんな感じ:

#!/bin/bash
basedir=$(cd $(dirname $0)/.. && pwd)
exec \
     env \
     HUBOT_IRC_SERVER=your.irc.server \
     HUBOT_IRC_PORT=6667 \
     HUBOT_IRC_PASSWORD=PASSWORD_IF_REQUIRED \
     HUBOT_IRC_ROOMS="#hubot-test" \
     HUBOT_IRC_NICK="myhubot" \
     HUBOT_ADAPTER=irc \
     HUBOT_NAME=myhubot \
     $basedir/bin/hubot

これを実行すると,Hubot が指定した IRC サーバのチャネルに接続され,先のシェル上でのインタラクティヴと同様なことが IRC 上で行えるようになります.追加で設置した scripts/hello.coffee も機能してますね:

Slack に接続する: slack アダプタ

メッセージングツールの 1種である Slack と連携してみます.

Integration を追加する

チーム設定の「Integrations」メニューにて,「Hubot」Integration を追加します.その詳細ページにおける「Token」が設定に必要になってきます.

起動のための準備

node モジュール hubot-slack を追加:

% npm install hubot-slack --save && npm install
npm WARN package.json hubot-maps@0.0.0 No repository field.
hubot-slack@2.2.0 node_modules/hubot-slack
npm WARN package.json hubot-maps@0.0.0 No repository field.
% git diff
diff --git a/package.json b/package.json
index a90d37f..a9cf617 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
     "hubot-rules": "^0.1.0",
     "hubot-scripts": "^2.5.16",
     "hubot-shipit": "^0.1.1",
+    "hubot-slack": "^2.2.0",
     "hubot-youtube": "^0.1.2"
   },
   "engines": {

起動用シェルスクリプトを準備:

% touch bin/run_slack
% chmod +x bin/run_slack

中身はこんな感じ:

#!/bin/bash
basedir=$(cd $(dirname $0)/.. && pwd)
exec \
    env \
    PORT="8888" \
    HUBOT_SLACK_TOKEN=YOUR_SECRET_TOKEN \
    HUBOT_SLACK_TEAM=YOUR_TEAM \
    HUBOT_SLACK_BOTNAME=hubot \
    HUBOT_SLACK_CHANNELMODE=whitelist \
    HUBOT_SLACK_CHANNELS=hubot-test \
    HUBOT_SLACK_ADAPTER=slack
    HUBOT_NAME=hubot \
    $basedir/bin/hubot

アダプタが slack である Hubot を起動すると,Slack でメッセージが書き込まれた際に発生する Webhook リクエストを受け取るための窓口となる HTTP サーバも立ち上がります.そのポートを,環境変数 PORT で指定します.(デフォルト知らない.)

起動してみる

まずは手元の環境で起動して簡単な確認など:

% ./bin/hubot_slack
npm WARN package.json hubot-maps@0.0.0 No repository field.
connect deprecated multipart: use parser (multiparty, busboy, formidable) npm module instead node_modules/hubot/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js:56:20
connect deprecated limit: Restrict request size at location of read node_modules/hubot/node_modules/express/node_modules/connect/lib/middleware/multipart.js:86:15
Slack adapter options: { token: 'YOUR_SECRET_TOKEN',
  team: 'YOUR_TEAM',
  name: 'hubot',
  mode: 'whitelist',
  channels: [ 'hubot-test' ],
  link_names: 0 }
Successfully 'connected' as hubot
[Fri Nov 21 2014 12:12:58 GMT+0900 (JST)] ERROR hubot-heroku-alive included, but missing HUBOT_HEROKU_KEEPALIVE_URL. `heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s  | grep web_url | cut -d= -f2)`
[Fri Nov 21 2014 12:12:58 GMT+0900 (JST)] INFO Using default redis on localhost:6379

※ トークンが間違ってたりしても Successfully 'connected' as hubot とか出るのであまりあてになりません.

立ち上がった HTTP サーバとの簡単な確認.

Hubot 起動前:

% curl -i http://localhost:8888/hubot/slack-webhook -F user_name=issm -F text=foobar
curl: (7) Failed connect to localhost:8888; Connection refused

Hubot 起動後:

% curl -i http://localhost:8888/hubot/slack-webhook -F user_name=issm -F text=foobar
HTTP/1.1 100 Continue
 
HTTP/1.1 200 OK
X-Powered-By: hubot/hubot
Date: Fri, 21 Nov 2014 03:13:02 GMT
Connection: keep-alive
Transfer-Encoding: chunked

※ 実際にはこれで Slack に影響は出ないはず.

Slack から Webhook を呼べるようにする

Heroku を使わない例

巷では「Slack の bot を Hubot で作って Heroku にデプロイした」的なエントリが飛び交っているため,ここでは自前のサーバを利用する例を挙げておきます.

Slack からの呼び出し先

先の「Hubot Integration」詳細ページにおける「Hubot URL」という項目で,イベントが発生したときに(?)Slack からの Webhook 呼び出し先の基本 URL を指定します.

例えば https://webhook.iss.ms/ と設定した場合,実際に呼び出される URL は https://webhook.iss.ms/hubot/slack-webhook となります.

アプリケーションをデプロイする

まぁテキトーに.

そして,デプロイ先で Hubot を起動しておきます.

nginx から Hubot の HTTP サーバへプロキシさせる

「Hubot URL」 が https://webhook.iss.ms/hubot/xFOdXMN2gWX5oBPa/ であるとします.

ピンポイントでプロキシされればよいので,nginx 設定を次のような感じに:

server {
    server_name webhook.iss.ms;
    listen 443;
 
    ...
 
    ### hubot
    location = /hubot/xFOdXMN2gWX5oBPa/hubot/slack-webhook {
        proxy_pass http://localhost:8888/hubot/slack-webhook;
        ...
    }
}

nginx を再起動して,先と同様に curl を打ってそれっぽいレスポンスがあればよさげです:

% curl -i https://webhook.iss.ms/hubot/xFOdXMN2gWX5oBPa/hubot/slack-webhook -F user_name=issm -F text=hello
HTTP/1.1 100 Continue
 
HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: Fri, 21 Nov 2014 03:40:35 GMT
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: hubot/hubot

※ これだけでは Slack には何もいかないはず.

Slack からメッセージを投げてみる

こんな感じ:

拡張分も動いてくれています.

おわりに

以上,bot フレームワーク Hubot について,そのインストール,3種のアダプタ shellircslack の利用,スクリプトによる挙動の拡張,についてざっと試したことをまとめてみました.

次のステップとしては,拡張スクリプト内で,お仕事関連の Web API との連携あたりを徐々に構築していくとかそんなところでしょうか.node プログラミングのお作法とかほとんど知らないのでそこからになりますがw