Help us understand the problem. What is going on with this article?

Elixir - Hedwig Responderを書く

More than 3 years have passed since last update.

この記事は リクルートライフスタイル Advent Calendar 2016 の3日目の記事です。

はじめに

ビューティ開発Tの@shotatです。
今回は「Elixir製botフレームワークのHedwigのResponder作成」について書きます。
bot作成は普通にHubot使うのが一番楽なんですが、Elixirを書きたいがためにHedwigを使っていきます。

正直Elixir力は全然高くないので、間違った箇所があればご指摘いただけると幸いです。

Hedwigについて

https://github.com/hedwig-im/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リポジトリを参考にしました。

https://github.com/enilsen16/awesome-hedwig

先月くらいまではResponders欄に2件いた気がするんですが、現時点で再確認したら半減していました。Hedwig界のエコシステムはまだまだ黎明期と言えるので、自作のモジュールを作成するチャンスです。

作ったもの

https://github.com/shotat/hedwig_github

hoge.png

<bot_name>: github <repository_name> とreplyを送るとマッチしたGitHubのリポジトリ + スター数を送ってくれます。極稀に役に立っています。

昨今においてはコンプライアンス遵守の重要性が叫ばれているため、なんとなくモザイク処理をしておきました。

作り方

とりあえず mix new でプロジェクトを作成します。

次に mix.exs にhedwigと必要なライブラリ系をつっこみます。 tentacat はGitHubのAPI wrapperです。

mix.exs
  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を実装していきます。

github.ex
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等で簡単に運用できます。便利な世の中ですね。

recruitlifestyle
飲食・美容・旅行領域の情報サイトや『Airレジ』などの業務支援サービスなど、日常消費領域に関わるサービスの提供するリクルートグループの中核企業
http://www.recruit-lifestyle.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away