この記事は リクルートライフスタイル Advent Calendar 2016 の3日目の記事です。
はじめに
ビューティ開発Tの@shotatです。
今回は「Elixir製botフレームワークのHedwigのResponder作成」について書きます。
bot作成は普通にHubot使うのが一番楽なんですが、Elixirを書きたいがためにHedwigを使っていきます。
正直Elixir力は全然高くないので、間違った箇所があればご指摘いただけると幸いです。
Hedwigについて
冒頭にも書きましたがElixir製のbotフレームワークです。
Hedwig is a chat bot, highly inspired by GitHub's Hubot.
と、READMEに書いてある通り、書き方は非常にHubotに似ています。
Hubotを使ったことがあり、最低限のElixirの知識があれば基本的な対話の実装はできます。
Slackで動かすまでの日本語のチュートリアル的なものは以下の記事にまとめています。
Elixir製Hubot風BotフレームワークのHedwigでSlack Botを作る - Memento memo.
Responderを作る
Responderは「pingと呟くとPONGを返す」みたいなscriptのことです。
ドキュメントを読むとResponderはbot appの lib/responders/xxxxx.ex
に直接書けばいいんですが、どうせなら外部モジュールに切り出してプラグインっぽくしたいので、今回はそれをやりました。
以下のHedwigのawesomeリポジトリを参考にしました。
先月くらいまではResponders欄に2件いた気がするんですが、現時点で再確認したら半減していました。Hedwig界のエコシステムはまだまだ黎明期と言えるので、自作のモジュールを作成するチャンスです。
作ったもの
<bot_name>: github <repository_name>
とreplyを送るとマッチしたGitHubのリポジトリ + スター数を送ってくれます。極稀に役に立っています。
昨今においてはコンプライアンス遵守の重要性が叫ばれているため、なんとなくモザイク処理をしておきました。
作り方
とりあえず mix new
でプロジェクトを作成します。
次に mix.exs
にhedwigと必要なライブラリ系をつっこみます。 tentacat
はGitHubのAPI wrapperです。
def application do
[applications: [
:hedwig,
:tentacat,
],
mod: {HedwigGithub, []}]
end
...
defp deps do
[
{:tentacat, "~> 0.5"},
{:hedwig, "~> 1.0.0-rc.4"}
]
end
lib/<app_name>/responders/<responder_name>.ex
にResponderを実装していきます。
defmodule HedwigGithub.Responders.Github do
use Hedwig.Responder
@usage """
hedwig: github <repository name> - Respond with GitHub url with stars count.
"""
respond ~r/github(?: +)(.+)/i, msg do
%{matches: %{1 => q}} = msg
reply msg, search_repository(q)
end
def search_repository(repository_name) do
client = Tentacat.Client.new
params = %{
q: repository_name,
per_page: 1,
}
options = [ pagination: :none ]
response = Tentacat.get "search/repositories", client, params, options
case response do
%{"incomplete_results" => false, "items" => [item | _]} ->
parse_item(item)
_ ->
"?"
end
end
defp parse_item(item) do
%{"html_url" => url, "stargazers_count" => stars} = item
"#{url} :star: #{stars}"
end
end
あまり本筋とは関係ないですが、実装当時Tentacatのsearchモジュールが怪しい挙動をしていたので直接getを呼んでいます。Tentacat使った意味の7割くらいが消えています。
Responderを使う側の実装
https://github.com/shotat/hedwig_github のREADMEに書きました。
とりあえず mix.exs
で依存定義してReponderのリストに追加すれば動きます。
まとめ
結構端折ってしまいましたが、Repositoryを覗いて頂ければ同じように作成できるかと思います。
Elixir自体書き味の良い言語なので、botあたりの簡単なところから初めつつ、こっそりプロダクトコードに突っ込んでいきたいです。
おまけ: deploy周り
素のElixirだと対応してるPaaSが存在しないので、Dockerを使います。
Dockerfile
の例は以下です。
FROM elixir
RUN mkdir /app
COPY . /app/
WORKDIR /app
RUN mix local.hex --force
RUN mix deps.get && mix compile
CMD ["mix", "run", "--no-halt"]
こんな感じでDockerコンテナで動くようにしておけばGAE等で簡単に運用できます。便利な世の中ですね。