Current section
Files
Jump to
Current section
Files
lib/xkcd.ex
defmodule Xkcd do
@moduledoc """
A client for the XKCD JSON API
"""
alias Xkcd.Comic
alias HTTPoison.Response
@base_url "https://xkcd.com"
@doc """
Takes a number from 1 to the latest and returns a tuple with with :ok and a
comic struct or an :error atom and an error message
Example:
iex> Xkcd.number(256)
{:ok, %Xkcd.Comic{...}}
iex> Xkcd.number(0)
{:error, "Comic Not Found"}
"""
@spec number(integer) :: {:ok, Comic.t}
| {:error, String.t}
def number(integer) do
"#{@base_url}/#{integer}/info.0.json"
|> get_comic
end
@doc """
Gets the latest comic and returns a tuple with :ok and a comic struct
Example:
iex> Xkcd.latest
{:ok, %Xkcd.Comic{...}}
"""
@spec latest :: {:ok, Comic.t}
def latest do
"#{@base_url}/info.0.json"
|> get_comic
end
@doc """
Gets a random comic and returns a tuple with :ok and a comic struct
Example:
iex> Xkcd.random
{:ok, %Xkcd.Comic{...}}
"""
@spec random :: {:ok, Comic.t}
def random do
{:ok, %Comic{num: max_num}} = Xkcd.latest
max_num
|> :rand.uniform
|> number
end
defp get_comic(url) do
url
|> HTTPoison.get([], follow_redirect: true)
|> get_body
|> parse_body
end
defp get_body({:ok, %Response{status_code: 404}}), do: {:error, "Comic Not Found"}
defp get_body({:ok, %Response{body: body}}), do: {:ok, body}
defp parse_body({:ok, body}), do: {:ok, Poison.decode!(body, as: %Comic{})}
defp parse_body(error), do: error
end