Introduction
Enjoy Elixir
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
$ 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
Enjoy Elixir
See all you next year.
-
12/31, 2021 ↩