Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
7
Help us understand the problem. What are the problem?

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について

冒頭にも書きましたが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界のエコシステムはまだまだ黎明期と言えるので、自作のモジュールを作成するチャンスです。

作ったもの

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

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
7
Help us understand the problem. What are the problem?