GitHub社謹製! bot開発・実行フレームワーク「Hubot」

第3回Hubotを色々なサービスと繋げてみる

今回は、HubotにサードパーティーのAdapterを導入してIRCとTwitterに接続してみます。サードパーティーのAdapterを使用するには、Hubotの設定方法について理解している必要があるため、まずHubotの設定方法について解説した後、それぞれのAdapterの使用方法について説明します。

Hubotの設定方法

Hubotの設定には、⁠使用するスクリプトの設定⁠⁠、⁠Hubot自身が使用する設定」「スクリプトが使用する設定」の3種類があり、それぞれ設定方法が異なります。

使用するスクリプトの設定

使用するスクリプトを設定する方法は、大きく分けて3種類あります。

特定のディレクトリにスクリプトファイルを配置する

おもに、自作のスクリプトを使用するときに使用します。Hubotは、初期状態で起動時に次のディレクトリをスキャンしてディレクトリに含まれるスクリプトファイルを読み込みます。

  • ./scripts
  • ./src/scripts

自作のスクリプトをscriptsディレクトリに配置し、不要になった場合はscriptsディレクトリから削除するという運用が簡単です。

hubot-scripts.json

Hubotの公認コミュニティスクリプトであるhubot-scriptsリポジトリに含まれるスクリプトを使用します。hubot-scriptsリポジトリは、Hubot起動時にnpmで自動的にインストールされてnode_modulesディレクトリに保存されていますので、手動でモジュールを導入する必要はなく、このjsonファイルでスクリプト名を指定するだけで読み込むことができます。

ただし、Hubotはスクリプトが必要とするnpmモジュールの依存関係までは自動で解決してくれません。そのため、必要に応じてpackage.jsonに依存モジュールを追記してモジュールをインストールする必要があります。

hubot-scripts.jsonは、単純に1つの配列のみが入っており、その配列の各要素にスクリプト名を書いていくことになります。hubot-scripts.jsonの記述例を次に示します。

["redis-brain.coffee", "shipit.coffee"]

hubot-scriptsリポジトリには、Hubotのチャット上での挙動を制御する通常のスクリプトだけでなく、Redisを永続化のストレージとして使うためのスクリプトなどHubot自体に機能を追加するスクリプトも含まれているため、お世話になることは多いと思います。

external-scripts.json

記述方法は、hubot-scripts.jsonと同じですが、読み込み対象がhubot-scriptsではなく独自に導入したnpmのパッケージになります。記述方法はhubot-scripts.jsonと同じです。

たとえばfooモジュールをhubotにロードさせたい場合は次のように記述します。

["foo"]

たとえば、hubot-scriptsには入っていないがnpmで公開されているスクリプトをpackage.jsonに追加してexternal-scripts.jsonで読み込む、と言った用途で使います。

Hubot自身が使用する設定

Hubot自身が使用する設定は、Hubot起動時のコマンドライン引数か環境変数のどちらかで指定します。コマンドライン引数で設定できるオプションはいずれも環境変数でも指定することができ、同じ設定値をコマンドライン引数と環境変数の両方で指定した場合にはコマンドライン引数が優先されます。

使用可能な設定項目の一覧は、Hubotのコマンドhubot -hか、hubotコマンドのソースコードで確認できます。

設定項目の例を次表に示します。

引数引数
(省略形)
環境変数用途
--name NAME-nHUBOT_NAMEhubotの対話上の名前を指定
--alias ALIAS-lHUBOT_ALIAShubotの別名を指定。HUBOT_NAMEとあわせて指定するとhubotがHUBOT_NAMEとHUBOT_ALIASの両方に反応するようになります
--adapter ADAPTER-aHUBOT_ADAPTER使用するアダプタ名のうちhubot-fooのfooの部分を指定
--disable-httpd-dHUBOT_HTTPhttpd機能を停止するかどうかを指定

スクリプトが使用する設定

Hubot自身が使用する設定値は、コマンドライン引数でも環境変数でも指定できますが、Adapterや個別のスクリプトの設定値は環境変数でしか設定できません。

環境変数はどのように設定しても構いませんが、開発中は⁠Hubotを起動するためのシェルスクリプト⁠を用意してそのシェルスクリプトの中に設定を書いておくと便利です。具体的には、次のようなシェルスクリプトを書くことになります。

run_hubot.sh
#!/bin/sh

export HUBOT_ADAPTER=hubot-irc
export HUBOT_NAME=myhubot

bin/hubot

以後、Adapterなどで使用する設定値は、シェルスクリプトを書いて環境変数を設定する方式で説明しますが、適宜自分にとって都合の良い方法に読み替えてください。

初期状態のエラーを解消する方法について

前回Hubotの起動を試みた時、何も設定していない状態では2種類のエラーメッセージが表示されていました。これらの問題を解決するには、どのような設定を施せば良いでしょうか。

初期状態で表示されるエラーは次のような内容です。

(A) WARNING The HUBOT_AUTH_ADMIN environment variable not set
(B) ERROR [Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED]

まず、(A)について、このメッセージは、scripts/auth.coffeeスクリプトがHUBOT_AUTH_ADMIN環境変数が設定されていないことを警告するものです。auth.coffeeスクリプトは、チャットに参加するユーザにroleを割り当て、スクリプトがroleを参照して実行権限を判断できるようになる機能を提供します。その中で、HUBOT_AUTH_ADMIN環境変数は、adminのroleを持つユーザを設定するために使われます。しかし、auth.coffeeスクリプトの使い方は少し複雑なので、最初はscriptsディレクトリから削除しておいて、必要に応じて復活させると良いでしょう。

次に(B)について、Hubotを雛形から起動した場合はデフォルトで永続化機能⁠brain⁠のドライバとしてRedisが使われており、Hubot起動時にデフォルトでの接続先であるlocalhost:6379に接続できないためエラーとなっています。HubotがRedisを使用するよう設定しているファイルは、hubot-scripts.jsonです。初期状態でのhubot-scripts.jsonの中身を次に示します。

["redis-brain.coffee", "shipit.coffee"]

このredis-brain.coffeeという項目を削除すると、Redisに接続しないようになるため(B)のエラーが出なくなります。もちろん、その代わりにRedisでの永続化機能は使えなくなるため、必要に応じてRedisを用意したうえで設定を復活させるということになります。

ちなみに、shipit.coffeeは、リスの画像を表示するスクリプトです。不要ならこれも削除してしまって問題ありません。

Adapterについて

Hubotは、チャットツールからの入力をスクリプトで解釈し、スクリプトの出力をチャットツールに伝えます。ここで、チャットツールとの入出力を担当するモジュールをAdapterと呼びます。どのAdapterを使うかはHubotの起動時に指定し、何も指定しない場合は⁠shell⁠Adapterが使われます。また、同時に使用できるAdapterは1種類のみです。

図1 Adapterとチャットツールの関係
図1 Adapterとチャットツールの関係

Adapterを使用するには、Adapterのモジュールをインストールして、Adapterごとに指定された設定を施したうえでHubotを起動する必要があります。

Adapterの使用上の注意点として、Adapterがどのような機能を実装しているかは、Adapterに依存しているということがあります。Adapterは、Adapterクラスを継承して実装しますが、たとえば、hubot-twitterはスクリプトからは実質的にsendメソッドしか使えませんし、音を鳴らすplayメソッドは音を鳴らす機能の無いチャットツールでは使えないため実装していないAdapterが多いです。とは言え、普段使うのはsendメソッドであり、sendメソッドは基本的にどのAdapterでも実装されているので、問題になることは少ないとは思います。

また、⁠チャットツールとどう接続するのか」という部分もAdapterの実装に依存しています。たとえば、hubot-ircはIRCクライアントとしてIRCサーバと通信しますが、hubot-twitterはStreaming APIを通じてPublic Timelineから自分の名前を含んだ投稿を検索して入力とします。

IRCのような基本的な機能を持ったチャットツールとの接続では躓く部分は少ないと思いますが、自分が使いたいチャットツールに接続するためのAdapterを使用するときにうまくいかなかったり、ドキュメントでは動作が理解できない場合は、Adapter自体のソースコードを読んでみることをお勧めします。

今回は、TwitterとIRCのAdapterを通じてAdapterの使い方について具体的に説明しますが、Adapterは日々改良され続けているため、今回説明する内容は記事執筆時点の仕様である点に注意してください。最新情報は常にドキュメントとソースコードです。

Twitterとの接続

Twitterとの接続に使用できるAdapterとして、hubot-twitterが公開されています。このAdapterの動作原理を次図に示します。

図2 TwitterとAdapterの接続
図2 TwitterとAdapterの接続

Twitterは、IRCなどのチャットツールと異なりチャットルームがあって参加者が居て、という構成にはなっていないため、チャットツール用のbotであるHubotを接続するにはAdapterの実装者がTwitterをAdapterの仕様に合わせて抽象化する必要があります。hubot-twitterの場合は、Twitterの公開タイムラインに自分の名前(HUBOT_NAME)を含む発言が流れてこないかStreaming APIで監視し、合致する発言があった場合にスクリプトによるリアクションをstatuses/updateでTwitterにポストします。

このような動作をするため、HUBOT_NAMEが一般的な単語の場合は、Hubotが公開タイムライン上を流れる単語に意図せず反応して発言者にリプライを返してしまう危険性があります。使用する場合は、挙動を理解したうえで慎重に試みてください。

Adapterのインストール

hubot-twitterはnpmで公開されているモジュールですので、npmを通じてインストールします。

$ npm install hubot-twitter --save && npm install

コマンドを実行すると、package.jsonのdependenciesの項目に次のようにhubot-twitterモジュールが追加されます。

"dependencies": {
  "hubot": ">= 2.6.0 < 3.0.0",
  "hubot-scripts": ">= 2.5.0 < 3.0.0",
  "hubot-twitter": "^2.1.1"
},

package.jsonを編集して直接上記と同様の内容を記述しても問題ありません。

Adapterの設定

hubot-twitterは、TwitterのAPIを使用して動くため、まずはHubotが使用するTwitterのアカウントがTwitterのAPIを使用できるようにする必要があります。

TwitterのAPIを使用できるようにするには、APIを使用したいアカウントでTwitterにログインしたうえでTwitterのApplication Management機能にアクセスし、アプリケーションを作成します。アプリケーションを作成したら、⁠API key⁠⁠、⁠API secret⁠⁠、⁠Access token⁠⁠、⁠Access token secret⁠の4つを取得してください。Hubotが発言をポストするために⁠Access level⁠⁠Read and Write⁠に設定することも重要です。

Twitter APIを使用する準備が整えば、後はHubot起動時にhubot-twitterが必要とする設定を読み込ませるために環境変数を設定するだけです。

run_hubot.sh
#!/bin/sh

export HUBOT_TWITTER_KEY="自分のAPI key"
export HUBOT_TWITTER_SECRET="自分のAPI secret"
export HUBOT_TWITTER_TOKEN="自分のAccess token"
export HUBOT_TWITTER_TOKEN_SECRET="自分のAccess token secret"

export HUBOT_NAME="自分のbotの名前"

bin/hubot -a twitter

実行

./run_hubot.shを実行すると、Hubotが起動してStreaming APIと接続した状態になります。Public Timelineで⁠自分のbotの名前 ping⁠のようにShell Adapterのときと同様のコミュニケーションを取ると、Hubotがリプライを返してきます。

hubot-twitterは、入力ソースがStreaming APIでPublic Timelineになるため、利用者のHubotへの動作指示をオープンにしなければならなかったり、取得したメッセージを解釈する処理が不安定だったりと、そのままでは若干使いにくい印象はあります。しかし、コードが短く内容も難しくは無いので、コードを読んで必要に応じて改良してみると良いかもしれません。

IRCとの接続

IRCとの接続に使用できるAdapterとして、hubot-irc が公開されています。このAdapterの動作原理を次図に示します。

図3 IRCチャンネルにhubotがjoin
図3 IRCチャンネルにhubotがjoin

hubot-ircでは、HubotがIRCサーバに一般の参加者と同様にIRCクライアントを通じて接続します。IRCクライアントにはnode-ircの派生版を使用しています。

Adapterのインストール

hubot-twitterと同様に次のコマンドでモジュールを追加するか、手動でpackage.jsonを編集してインストールしてください。

$ npm install hubot-irc --save && npm install

Adapterの設定

通常のIRCクライアントでIRCに接続するときと同様にIRCサーバに接続するための情報を設定します。SSL接続が必要だったりパスワードが必要だったりと、どのような設定が必要かは接続先のIRCサーバによって変わる筈ですので、お使いの環境にあわせてアレンジしてください。 設定の例を次に示します。

run_hubot.sh
#!/bin/bash

# 接続先IRCサーバのホスト
export HUBOT_IRC_SERVER="xxx.xxx.xxx.xxx"
# hubotのIRC上でのニックネーム。hubot-ircは内部でHUBOT_NAMEをこの設定値で上書きする点に注意が必要です
#export HUBOT_IRC_NICK="hubot"
# hubotが初期状態でログインするチャットルーム名
export HUBOT_IRC_ROOMS="#chatroom"

bin/hubot -a irc

上記の他にも様々な項目を設定できるようになっています。よく使いそうな項目を次表に示します。

設定項目用途
HUBOT_IRC_PORTIRCサーバのポート番号が6667でない場合に指定
HUBOT_IRC_PASSWORDIRCサーバがパスワードを要求する場合に指定
HUBOT_IRC_UNFLOODスクリプトによってhubotが多量のメッセージをIRCサーバにポストする時、メッセージをキューイングしてゆっくりとポストするようにする
HUBOT_IRC_USESSLIRCサーバへSSLで接続する必要がある場合に指定
HUBOT_IRC_SEND_NOTICE_MODEhubotがNOTICEで発言する

hubot-ircは他にも多くのオプションがあるため、ドキュメントソースコードを確認してみることをお勧めします 。

実行

上記の内容を設定したうえで./run_hubot.shを実行すると、Hubotが#chatroomチャンネルにjoinしてきます。

図4 IRCチャンネルにHubotがjoin
図4 IRCチャンネルにHubotがjoin

IRC上のHubotは一般ユーザと同じ扱いですので、最初に設定したチャンネル以外のチャンネルにinviteしたりoperator権限を与えたり取り除いたりといった操作が普通にできます。

また、スクリプトが他のAdapterとの互換性を失ってしまうためお勧めはしませんが、次のような記述をすることでプライベートメッセージを送ったり、特定のチャンネルにjoinしたりといったIRC固有の機能を使うこともできます。

module.exports = (robot) ->
  robot.hear /foo/, (msg) ->
    robot.adapter.sendPrivate msg.envelope, 'bar'

まとめ

今回は、Hubotの設定方法とAdapterの使用方法を解説しました。上記で説明したIRCやTwitter以外の様々なチャットツールとも、同様の手順でAdapterを導入することで接続できます。ぜひ、皆さんの使用しているチャットツールに適したAdapterを探してHubotを接続してみてください。

次回は、Hubotスクリプトの基本的な書き方について解説します。

参考文献

おすすめ記事

記事・ニュース一覧