5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

サンプルAdvent Calendar 2021

Day 22

Liker likes any tweets with "#大晦日ハッカソン" hash tag on 12/31, 2021 -- Enjoy Elixir !!!

Posted at

Introduction

Enjoy Elixir:bangbang::bangbang::bangbang:

Today1 I take part in an event.
Its event is "Omisoka hackathon".
Omisoka means December 31th in Japananese.
December 31th is called Omisoka in Japananese.

This event rules to tweet with "#大晦日ハッカソン" hash tag.

I made an app.
Its app is called Liker.
Liker likes any tweets with "#大晦日ハッカソン" hash tag.

Write -- aka Enjoy Elixir:bangbang::bangbang::bangbang:

$ mix new liker --sup

mix.exs

mix.exs
  defp deps do
    [
      {:oauther, "~> 1.3"},
      {:jason, "~> 1.3"},
      {:extwitter, "~> 0.13.0"},
      {:quantum, "~> 3.4"},
      {:timex, "~> 3.7"}
    ]
  end
  • oauther
    • A library to authenticate using the OAuth 1.0 protocol.
  • jason
    • A blazing fast JSON parser and generator in pure Elixir.
  • extwitter
    • Twitter client library for Elixir.
  • quantum
    • Cron-like job scheduler for Elixir.
  • timex
    • Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you!

lib/liker/twitter/api.ex

lib/liker/twitter/api.ex
defmodule Liker.Twitter.Api do
  @query "#大晦日ハッカソン -RT"
  @ignores []

  def search(last_created_at \\ 0) do
    response =
      ExTwitter.search(
        @query,
        count: 100,
        search_metadata: true
      )

    response.statuses
    |> statuses(last_created_at)
    |> do_search_next_page(response.metadata, last_created_at, [])
  end

  def create_favorite(id) do
    try do
      ExTwitter.create_favorite(id, [])
    rescue
      [ExTwitter.Error] -> IO.puts("You have already favorited this status.")
    end
  end

  defp do_search_next_page([], _metadata, _last_created_at, result_list), do: result_list

  defp do_search_next_page(prev_page_list, metadata, last_created_at, result_list) do
    response = ExTwitter.search_next_page(metadata)

    response.statuses
    |> statuses(last_created_at)
    |> do_search_next_page(response.metadata, last_created_at, result_list ++ prev_page_list)
  end

  defp statuses(statuses, last_created_at) do
    statuses
    |> Enum.map(fn %{
                     id: id,
                     id_str: id_str,
                     text: text,
                     created_at: created_at,
                     user: %{
                       profile_image_url_https: profile_image_url_https,
                       screen_name: screen_name
                     },
                     favorited: favorited
                   } ->
      %{
        id: id,
        id_str: id_str,
        text: text,
        created_at:
          Timex.parse!(created_at, "{WDshort} {Mshort} {D} {h24}:{m}:{s} +0000 {YYYY}")
          |> Timex.to_unix(),
        profile_image_url_https: profile_image_url_https,
        screen_name: screen_name,
        url: "https://twitter.com/#{screen_name}/status/#{id_str}",
        favorited: favorited
      }
    end)
    |> Enum.reject(fn %{screen_name: screen_name} -> screen_name in @ignores end)
    |> Enum.reject(fn %{favorited: favorited} -> favorited end)
    |> Enum.filter(fn %{created_at: created_at} -> created_at > last_created_at end)
  end
end

lib/liker/created_at_agent.ex

lib/liker/created_at_agent.ex
defmodule Liker.CreatedAtAgent do
  use Agent

  def start_link(_initial_value) do
    created_at = Timex.now() |> Timex.to_unix() |> Kernel.-(20000)
    Agent.start_link(fn -> %{created_at: created_at} end, name: __MODULE__)
  end

  def get, do: Agent.get(__MODULE__, & &1)

  def update(created_at) do
    Agent.update(__MODULE__, fn _ ->
      %{created_at: created_at}
    end)
  end
end

lib/liker/scheduler.ex

lib/liker/scheduler.ex
defmodule Liker.Scheduler do
  use Quantum, otp_app: :liker
end

lib/liker/application.ex

lib/liker/application.ex
  def start(_type, _args) do
    children = [
      Liker.CreatedAtAgent, # add
      Liker.Scheduler # add
    ]

lib/liker.ex

lib/liker.ex
defmodule Liker do
  def run do
    statuses =
      last_created_at()
      |> Liker.Twitter.Api.search()

    statuses
    |> Enum.map(fn %{id: id} ->
      Liker.Twitter.Api.create_favorite(id)
    end)

    update_created_at(statuses)
  end

  defp last_created_at do
    %{created_at: created_at} = Liker.CreatedAtAgent.get()

    created_at
  end

  defp update_created_at([]), do: nil

  defp update_created_at(statuses) do
    statuses
    |> Enum.map(fn %{created_at: created_at} -> created_at end)
    |> Enum.max()
    |> Liker.CreatedAtAgent.update()
  end
end

config/config.exs

config/config.exs
import Config

config :extwitter, :oauth,
  consumer_key: System.get_env("STSP_TWITTER_CONSUMER_KEY"),
  consumer_secret: System.get_env("STSP_TWITTER_CONSUMER_SECRET"),
  access_token: System.get_env("STSP_TWITTER_ACCESS_TOKEN"),
  access_token_secret: System.get_env("STSP_TWITTER_ACCESS_TOKEN_SECRET")

config :liker, Liker.Scheduler,
  jobs: [
    # Every 20 minutes
    {"*/20 * * * *", {Liker, :run, []}}
  ]

Run

$ mix deps.get
$ iex -S mix

Wrapping up :lgtm::lgtm::lgtm::lgtm::lgtm::lgtm:

Enjoy Elixir:bangbang::bangbang::bangbang:

See all you next year.

  1. 12/31, 2021

5
0
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
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?