Ⅲ. HubotによるBotの作成

1. Botの雛形を作成

※ 以降の作業は適当な作業ディレクトリを作って行ってください。
また、以降の説明はカレントディレクトリが作成した作業ディレクトリである前提で進みます。

yeoman (ヨーマン)でbotの雛形を作成する

以下コマンドを叩くとHubotのテンプレートの作成が始まる

yo hubot

また、以下の入力が求められるので、適宜入力する。

  • Owner
    所有者を表す情報(メールアドレスなど)。
    省略可能(デフォルト値が設定される)。

  • Bot name
    Botの名前。
    任意に入力可能。
    省略可能(ディレクトリ名が設定される)。

  • Description A simple helpful robot for your Company
    Botの概要。
    省略可能。

  • Bot adapter
    Botのアダプターを選択。
    今回はSlack向けのBotなので"slack"と入力

yo hubot
? ==========================================================================
We're constantly looking for ways to make yo better! 
May we anonymously report usage statistics to improve the tool over time? 
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes
                     _____________________________  
                    /                             \ 
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             / 
 ======= |[^_/\_]|   /----------------------------  
  |   | _|___@@__|__                                
  +===+/  ///     \_\                               
   | |_\ /// HUBOT/\\                             
   |___/\//      /  \\                            
         \      /   +---+                            
          \____/    |   |                            
           | //|    +===+                            
            \//      |xx|                            

? Owner example@com
? Bot name botname
? Description A simple helpful robot for your Company
? Bot adapter (campfire) slackgot back false
? Bot adapter slack
  ・
  ・
  ・

2. Hubotの起動

以下コマンドで、Hubotを起動する

sudo PORT=80 HUBOT_SLACK_TOKEN=XXXXX bin/hubot -a slack

ポイント

  1. 環境変数

    • PORT
      Hubotが利用するポート番号を指定する。ポート番号は任意のものを利用できるが、今回はVagrantのプロビジョニングで80番ポートを開けているので、80を利用する。

    • HUBOT_SLACK_TOKEN
      「Ⅰ. SlackとHubotの連携」で設定を行った際に、発行されたトークンを設定する。

  2. hubotコマンドのオプション

    • -a slack
      Hubotのアダプターを指定する。今回はSlackのBotを作成するため、Slackを指定する。

3. Hubotのライブラリを使ってみる

yeomanで作成したHubotの雛形にはサンプルソースが含まれている

scripts/example.coffee

サンプルソースの多くはコメントアウトされているので、コメントアウトを外して、下記の robotオブジェクトのメソッド を参考に、サンプルソースの動きを確認してみてください。

example.coffee(コメントアウトを除き、補足コメントを追加)

# Description:
#   Example scripts for you to examine and try out.
#
# Notes:
#   They are commented out by default, because most of them are pretty silly and
#   wouldn't be useful and amusing enough for day to day huboting.
#   Uncomment the ones you want to try and experiment with.
#
#   These are from the scripting documentation: https://github.com/github/hubot/blob/master/docs/scripting.md

module.exports = (robot) ->

  ###
  第一引数の"/badger/i"は正規表現で、
  最後に"i"を付与することマッチングの際、大文字小文字を無視する
  ###
  robot.hear /badger/i, (res) ->
    res.send "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS"

  robot.respond /open the (.*) doors/i, (res) ->
    doorType = res.match[1]
    if doorType is "pod bay"
      res.reply "I'm afraid I can't let you do that."
    else
      res.reply "Opening #{doorType} doors"

  robot.hear /I like pie/i, (res) ->
    res.emote "makes a freshly baked pie"

  lulz = ['lol', 'rofl', 'lmao']

  robot.respond /lulz/i, (res) ->
    # res.random は配列の要素をランダムで1つ返すメソッド
    res.send res.random lulz

  robot.topic (res) ->
    res.send "#{res.message.text}? That's a Paddlin'"


  enterReplies = ['Hi', 'Target Acquired', 'Firing', 'Hello friend.', 'Gotcha', 'I see you']
  leaveReplies = ['Are you still there?', 'Target lost', 'Searching']

  robot.enter (res) ->
    res.send res.random enterReplies
  robot.leave (res) ->
    res.send res.random leaveReplies

  answer = process.env.HUBOT_ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE_THE_UNIVERSE_AND_EVERYTHING

  robot.respond /what is the answer to the ultimate question of life/, (res) ->
    unless answer?
      res.send "Missing HUBOT_ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE_THE_UNIVERSE_AND_EVERYTHING in environment: please set and try again"
      return
    res.send "#{answer}, but what is the question?"

  robot.respond /you are a little slow/, (res) ->
    setTimeout () ->
      res.send "Who you calling 'slow'?"
    , 60 * 1000

  annoyIntervalId = null

  robot.respond /annoy me/, (res) ->
    if annoyIntervalId
      res.send "AAAAAAAAAAAEEEEEEEEEEEEEEEEEEEEEEEEIIIIIIIIHHHHHHHHHH"
      return

    res.send "Hey, want to hear the most annoying sound in the world?"
    annoyIntervalId = setInterval () ->
      res.send "AAAAAAAAAAAEEEEEEEEEEEEEEEEEEEEEEEEIIIIIIIIHHHHHHHHHH"
    , 1000

  robot.respond /unannoy me/, (res) ->
    if annoyIntervalId
      res.send "GUYS, GUYS, GUYS!"
      clearInterval(annoyIntervalId)
      annoyIntervalId = null
    else
      res.send "Not annoying you right now, am I?"

  ###
  Webサーバとして機能することも可能。
  下記処理は、「http://192.168.10.200/hubot/chatsecrets/XXX」という
  URIにPOSTメソッドでアクセスするとメソッドが呼び出される。
  ###
  robot.router.post '/hubot/chatsecrets/:room', (req, res) ->
    room   = req.params.room
    data   = JSON.parse req.body.payload
    secret = data.secret

    robot.messageRoom room, "I have a secret: #{secret}"

    res.send 'OK'

  robot.error (err, res) ->
    robot.logger.error "DOES NOT COMPUTE"

    if res?
      res.reply "DOES NOT COMPUTE"

  robot.respond /have a soda/i, (res) ->
    # Get number of sodas had (coerced to a number).
    sodasHad = robot.brain.get('totalSodas') * 1 or 0

    if sodasHad > 4
      res.reply "I'm too fizzy.."

    else
      res.reply 'Sure!'

      robot.brain.set 'totalSodas', sodasHad+1

  robot.respond /sleep it off/i, (res) ->
    robot.brain.set 'totalSodas', 0
    res.reply 'zzzzz'

robotオブジェクトのメソッド

それぞれのメソッドはそれぞれの一定の条件で呼び出され、呼び出されたメソッドの処理はコールバック関数内に定義します。
また、コールバックの引数のresオブジェクトのsendメソッドを呼ぶことによってSlackにメッセージを返すことができます。

respond (message, callback(res))

messageに含まれるワードが投稿されると呼ばれるメソッド。
hearとの違いはBotにメンションをしないと呼ばれない。

例) Botの名前が"botname"で、ソースが以下の場合

robot.respond (/hello.*/i, callback(res){
  // 処理
});

このメッセージには反応する

@botname hello makoto

このメッセージには反応しない

hello  makoto

hear (message, callback(res))

messageに含まれるワードが投稿されると呼ばれるメソッド。
respondとの違いはBotにメンションをしなくても呼ばれる。

enter (callback(res))

誰かがチャネルに参加した時に呼ばれるメソッド

leave (callback(res))

誰かがチャネルを抜けた時に呼ばれるメソッド

topic (callback(res))

トピックに変更があると呼ばれるメソッド

messageRoom (room, resMsg)

第一引数で指定したチャネルに、第二引数で指定したメッセージを送信する。

error (callback(err, res))

エラーが発生すると呼ばれるメソッド

robot.brainについて

Hubotにはデータ永続化の仕組みが備わっていて、robot.brainオブジェクトを利用することで、データの永続化が可能になります。 barinの内部ではKVS(key Value Store)方式のDBであるredisが利用されています。

brain.set(key, value)

例)

const key = 'key01';
let value = 'hogehoge';
brain.set(key, value)

brain.get(key)

例)

const key = 'key01';
let value = brain.set(key);
console.log(value); // hogehoge

robot.routerについて

Hubotはチャットのメッセージだけでなく、Webサーバとして機能させることもできます。
サンプルソースはpostメソッドを利用しているため、試しにくいですが、以下のようにgetメソッドを利用すればWebブラウザから簡単に試すことができます。

###
以下ソースを scripts/example.coffee に追加し、
Webブラウザで「http://192.168.10.200/test」にアクセスしてみてください。
###
robot.router.get '/test', (req, res) ->
  html = """
    <html>
    <script type="text/javascript">(function(){ alert('called from Hubot'); } )();</script>
    </html>
    """
  res.type 'html'

WebAPIの呼び出し

サンプルソースにはありませんが、Hubotは簡単にWebAPIを呼び出すことができます。

robot.http(url)

例)http://example.com/member/list からgetメソッドでデータを取得

robot.http('http://example.com/member/list')
  .get() ((err, res, body) => {
  let obj = JSON.parse(body);
});

詳しくは https://github.com/github/hubot/blob/master/docs/scripting.md#making-http-calls を参照

4. node-inspectorによるデバッグ

  1. 以下のコマンドでHubotを起動する

    sudo PORT=80 HUBOT_SLACK_TOKEN=XXXXX coffee --nodejs --debug node_modules/.bin/hubot -a slack
    
  2. node-inspectorの起動
    Hubotを起動したターミナルとは別途ターミナルを開く。
    開いたターミナルで以下のコマンドを起動。

    node-inspector
    

    起動すると以下のようにバージョン、とnode-inspectorにアクセスするためのURLが表示される

    node-inspector 
    Node Inspector v0.12.8
    Visit http://127.0.0.1:8080/?port=5858 to start debugging.
    
  3. node-inspectorの利用
    Chromeを開き、手順2で表示されたURLにアクセスする。
    node-inspector

  4. Chromeの開発者ツールと同じ要領でデバッグができます

results matching ""

    No results matching ""