LoginSignup
11
5

More than 5 years have passed since last update.

Slack botで通知したい投稿日のものを通知する with Qiita API

Last updated at Posted at 2018-06-08

(この記事は、「fukuoka.ex(その2) Elixir Advent Calendar 2017」の20日目、Slack Advent Calendar 2017の22日目です)

昨日は@koga1020さんの「PhoenixでMicrosoft Translator テキスト APIを利用してみる」でした!

はじめに

|> ElixirでSlack Botを作った with Qiita API
|> 定期的にSlack Botで記事を通知する with Qiita API
前回に引き続きSlack Botの作成を行います。前回ではSlackへの定期通知を実装を進めていきましたが、今回は取得したい日にちを指定して通知するようにします。

どうやるの?

Qiita APIには日にちを指定しての投稿の取得はありません、、ですので今考えつく方法としては取得したい日にちを指定し、Qiita APIをコール。指定した日にちが来るまでpageをスライドさせていく方法です。(なにか他にいい方法があれば教えて欲しいです)

概要

時間の操作ですとTimexが便利ですので早速使います。

実装

1. 日にちを指定して取得範囲をきめる

def daily_tag_items() do
  now = Timex.now("Asia/Tokyo")
  Storage.first(:tags)
  [token: token] = Application.get_all_env(:qiita)
  headers = [{"Authorization", "Bearer #{token}"}]
  channels = GenServer.call(ExAviso.Slack, {:channels})
  message = fetch_daily_tag_items(Storage.all(:tags), Timex.shift(now, days: -1), headers, channels)
end

Timex.nowでタイムゾーンを指定し、現在の日にちを取得できます。
Timex.shift(now, days: -1) で1日前の日にちをとります。Time.shift関数はアトムで指定した項目に対して、足したり引いたりをすることができます。さらに日にちのみではなく、年、月や時間も対象とできるので便利です。

2. 一番最初を取得

次にpageを一つずつスライドさせていき、指定した日にちのものが来るまでスライドをしていきます。

defp fetch_start_daily_tag_items({id, tag, _, per_page} = head, day, headers, page) do
  url = "https://qiita.com/api/v2/tags/#{tag}/items?page=#{page}&per_page=#{per_page}"
  body =
    case HTTPoison.get!(url, headers) do
      %{status_code: 200, body: body} ->
        Poison.Parser.parse!(body, keys: :atoms)

      %{error: "account_inactive"} = error ->
        IO.inspect(error)
    end
  days = Enum.filter(body, fn %{created_at: create_at} -> get_create_between_day(create_at, day, 1) end)
  if Enum.count(days) == 0 do
    fetch_start_daily_tag_items(head, day, headers, page + 1)
  else
    {page, days}    
  end
end

毎度のことながらHTTPoison.get!でリクエストを投げます。
返ってきた値でcreated_atが設定した範囲内かどうかをEnum.filterでチェックをしていきます。
ここで返り値に値が入っている(リストの要素数が0以外)場合は指定した日にちがあると判断できるので次の処理を行います。ちなみにEnum.filterで実行される関数をしたに記述します。

defp get_create_between_day(create_at, day, range) when is_integer(range) do
  after_day = Timex.shift(day, days: range - 1)
  Timex.between?(Timex.parse!(create_at, "{ISO:Extended}"), Timex.beginning_of_day(day), Timex.end_of_day(after_day))
end

Timex.between?関数で第一引数のものが第二引数、第三引数の間の日付なのかをboolで返します。
Timex.parse!では第一引数のものを第二引数でパースします。第二引数に{ISO:Extended}を指定していますが、これはISOのフォーマットとしてパースを行います。
Timex.beginning_of_dayはその日の最初の時間を(2018/6/8 22:15:00 -> 2018/6/8 00:00:00 )
Timex.end_of_dayはその日の最後の時間を(2018/6/8 22:15:00 -> 2018/6/8 23:59:59)
取得します。
この関数をEnum.filterで使い、指定した日付のものだけを抽出できるようにします。

3. 終了の日にち

次に指定した日付の最初のアイテムが取れたので最後のアイテムが取れるまでpageをスライドさせていきます。

defp fetch_end_daily_tag_items({id, tag, _, per_page} = head, day, headers, page, items) do
  url = "https://qiita.com/api/v2/tags/#{tag}/items?page=#{page}&per_page=#{per_page}"

  body =
    case HTTPoison.get!(url, headers) do
      %{status_code: 200, body: body} ->
        Poison.Parser.parse!(body, keys: :atoms)

      %{error: "account_inactive"} = error ->
        IO.inspect(error)
    end

  days = Enum.filter(body, fn %{created_at: create_at} -> get_create_between_day(create_at, day, 1) end)
  if Enum.count(days) == 0 do
    items
  else
    fetch_end_daily_tag_items(head, day, headers, page + 1, items ++ days)
  end
end

ここでさっきのfetch_start_daily_tag_itemsと違うのはEnum.filterでフィルタリングした値が0件の場合は指定した日付のものを取得し終えたと判定し、最後に連結したものを返します。
それまではレスポンスの値を次のデータに引き渡していきます。

結果

スクリーンショット 2018-06-09 1.02.04.png

お、無事に取れましたー

まだやってないこと

  • 今回は特定の日にちのみだったんですが、今度は週と月での範囲指定での取得を行いたいです。
  • あとはAPIコールをなんどもしてしまうので、、、ある程度制限する、もしくは別の方法で算出できるロジックを組みたい
  • その指定した日にちがない場合のことが考慮されてないので実装する

あしたは、@takasehidekiさんの「Erlang/OTPのソースビルドでHiPEが入らないときの対処法
です

最後に

  • Timexだと時間の整形や計算が楽だったのである程度使えるようになりたい。
  • Qiita APIの仕様とリクエスト数を考慮しながら作るのが難しい(今も悩み中)

:stars::stars::stars::stars::stars: 満員御礼!Elixir MeetUpを6月末に開催します :stars::stars::stars::stars::stars:
※応募多数により、増枠しました!!

「fukuoka.ex#11:DB/データサイエンスにコネクトするElixir」を6/22(金)19時に開催します。
自分もLTで発表させていただきますので、ぜひ興味ある方はご参加ください!

fukuokaex.png

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5