インフラブログ

とあるWEBサイトのインフラを構築運用するメモ

hubotを使ってhipchat上であれこれする

hubot hipchat

やりたいこと

チャットアプリのhipchatとボットとして動くhubotを使って、下記の事をしてみようと思い、設定してみました。 社内にあるubuntuでhubotを起動して、hipchat上にボットとして常駐させるようにします。

  • 運用するサイトに対する問い合わせが届いた際にチャットに通知する。

    • 不具合の問い合わせが複数回来た場合は携帯端末にpush通知する。
    • テキストスピーチで読み上げて社内のスピーカーで出力する
  • AWSで作業した履歴をチャットに通知する(履歴はCloudTrailで収集する)

処理の流れ

データ処理の流れは以下を想定しています。

  • 問い合わせ
     転送      ポスト         監視        読み上げ
Gmail------>MTA------>hipchat<---->hubot--->シェル(open_jtalk)
                         |
                         |push通知
                         |
                       携帯端末
AWS           ポスト             ポスト
cloudtrail ----------->hubot---------->hipchat
sns

 設定

下記は設定の記録です。

hipchat

部屋名をcontact,awsとして作成して、その部屋のRoom Notification Tokensも作成します。

hubot

社内のubuntuマシンにhubotをインストールしてひな形アプリも作成します。 hubotがログインの際に使うアカウントも作成して、起動確認まで行います。

$sudo apt-get install node
$sudo npm install -g hubot coffee-script
$sudo npm install -g yo generator-hubot
$mkdir -p examplebot
$cd examplebot
$yo hubot
 [?] Owner: app
 [?] Bot name: examplebot
 [?] Description: (A simple helpful robot for your Company) hogehoge
 [?] Bot adapter: (campfire) hipchat

$ cat hubot_env

 export PORT=5555
 export HUBOT_HIPCHAT_JID=xxxx_xxxx@chat.hipchat.com
 export HUBOT_HIPCHAT_PASSWORD=xxxx
 export HUBOT_HIPCHAT_ROOMS=xxxx_contact@conf.hipchat.com,xxxx_aws@conf.hipchat.com

$ source hubot_env
$ ./bin/hubot -a hipchat

問い合わせの対応

hipchatに問い合わせ内容をPOSTする

Gmailに転送設定をつけてMTAサーバにメールを転送します。 その後、/etc/aliasesに設定されたスクリプトが起動してhipchatにpostするようにします。

* /etc/aliases
contact: :include:/home/ec2-user/contact

* /home/ec2-user/contact
"| ruby contact.rb"
  • /home/ec2-user/contact.rb
#!/usr/bin/env ruby
# -*- encoding:utf-8 -*-
require 'hipchat'
require 'mail'

token = "xxxxxxxxxx"
room = "contact"
sender = "contact"

mail = Mail.new(STDIN.read)
body = mail.body.decoded.encode("UTF-8", mail.charset)

client = HipChat::Client.new(token, :api_version => 'v2')
client[room].send(sender, body)

問い合わせ内容を読み上げる

contact部屋にメッセージが追加されたら読み上げソフトウェアであるopen_jtalkを起動するようなスクリプトをhubotに追加します。

  • examplebot/scripts/contact.coffee
# Commands:
#   hubot contact
#
#   Commands:
#       hubot contact - 

spawn = require('child_process').spawn

module.exports = (robot) ->

  ROOM = ["contact"] # hipchatの部屋名
  SENDER = ["contact"] # hipchatのRoom Notification Tokensで設定したlabelに該当
  ENABLE = "contact_enable" # 読み上げるか読みあげないか(reidsのキー名)
  ERROR_COUNTER = "contact_error_counter" # 不具合報告のカウント数(reidsのキー名)
  REPORT_COUNT = 5 # この回数以上の不具合報告を受けたらpush通知
  MEMBERS = "@foo @bar" #push通知する対象のhipchatユーザ

  correct = (a, b) ->
    return true if a.join(" ").match(///#{b}///i)
    return false

  robot.hear /^off/i, (msg) ->
    return unless correct(ROOM, msg.message.room)
    robot.brain.set(ENABLE, 0)
    msg.send("読み上げを無効にしました。")

  robot.hear /^on/i, (msg) ->
    return unless correct(ROOM, msg.message.room)
    robot.brain.set(ENABLE, 1)
    msg.send("読み上げを有効にしました。")

  # msg.match[1]] 問い合わせの本文
  robot.hear /^(.*)$/i, (msg) ->
    return unless correct(ROOM, msg.message.room) \
              and correct(SENDER, msg.message.user.name) \
              and robot.brain.get(ENABLE) == 1

    # 不具合報告のような問い合わせがREPORT_COUNT回届いた時にpush通知を試みる。
    # 不具合報告が多い時はpush通知が連続されるのでトラブルとすぐに認識したい。
    if /(エラー|サーバ|重い)/.test(msg.match[1])
      cnt = robot.brain.get(ERROR_COUNTER)
      cnt ?= 0
      if cnt > REPORT_COUNT
        # @fooをつけることでメンションとなり、push通知されるみたい。
        msg.send(MEMBERS + " サーバトラブルのお問い合わせを受信")
      robot.brain.set(ERROR_COUNTER, (cnt++ % REPORT_COUNT))

    # 必要ないものは読み上げない
    return if msg.match[1].length < 10 || /(NGワード)/.test(msg.match[1])

    #読み上げ
    args = ['./bin/talk', "お問い合わせがきました。"+ msg.match[1]]
    cli = spawn('/bin/bash', args, {setsid: true})
    cli.stderr.on 'data', (data) ->
      console.log('cli stderr: ' + data.toString())
  • examplebot/bin/talk
#!/bin/sh

# yukkuri
#[ -f $yukkuri ] && echo $2 | $yukkuri | aplay

# jtalk
f=`mktemp`
wav=`mktemp`
score=$1
echo $2 > $f

emp="normal"
dic_dir="/var/lib/mecab/dic/open-jtalk/naist-jdic/"
voice="/home/app/MMDAgent_Example-1.4/Voice/mei/mei_${emo}.htsvoice"
open_jtalk -u 0.0 -jm 0.7 -jf 0.5 -a 0.55 -r 1.2 -m $voice -x $dic_dir -ow $wav $f
[ -s $wav ] && aplay $wav

exit 0