defmodule Allbud do
@moduledoc """
Documentation for `Allbud`.
"""
alias Allbud.Http
@letters Enum.map(?a..?z, fn x -> <<x::utf8>> end)
@doc """
Fetch all strains and strain profiles.
## Examples
```elixir
iex> Allbud.all()
```
"""
def all() do
strains =
Enum.map(@letters, fn x ->
{:ok, strain} = fetch_strains_by_letter(x)
strain
end)
|> List.flatten()
Enum.map(strains, fn x ->
fetch_strain_profile(x)
end)
end
@doc """
Fetch all strain names and url.
## Examples
```elixir
iex> Allbud.fetch_strains()
```
"""
def fetch_strains() do
Enum.map(@letters, fn x ->
{:ok, strain} = fetch_strains_by_letter(x)
strain
end)
end
@doc """
Fetch by letter strain names and url.
## Examples
```elixir
iex> Allbud.fetch_strains_by_letter("a")
```
"""
def fetch_strains_by_letter(params) do
{status, response} = Http.fetch_strains_by_letter(params)
case(status) do
:error ->
{:error, response.message}
:ok ->
html = response.body
{:ok, html} = Floki.parse_document(html)
result =
Floki.find(html, "#search-results")
|> Floki.find("div.title-box")
strains =
Enum.map(result, fn x ->
[{_, [{_, href}], [name]}] = Floki.find(x, "a")
{name, href}
end)
{:ok, strains}
end
end
@doc """
Fetch strain profile.
## Examples
```elixir
iex> Allbud.fetch_strain_profile({"strain name", "/"})
```
"""
def fetch_strain_profile(params) do
{name, _url} = params
{status, response} = Http.fetch_strain_profile(params)
case(status) do
:error ->
{:error, response.message}
:ok ->
html = response.body
{:ok, html} = Floki.parse_document(html)
result = Floki.find(html, "#strain_detail_accordion")
strain_percentages =
case Floki.find(result, "span.strain-percentages") do
[{_, _, [strain_percentages]}] -> strain_percentages
_ -> "unknown"
end
thc =
case Floki.find(result, "h4.percentage") do
[{_, _, [thc]}] ->
{thc, "unknown"}
[
{"h4", [{"class", "percentage"}],
[{"span", [{"class", "heading"}], ["THC: "]}, thc]}
] ->
{thc, "unknown"}
[
{"h4", [{"class", "percentage"}],
[
{"span", [{"class", "heading"}], ["THC: "]},
thc,
{"span", [{"class", "heading"}], ["CBN: "]},
{"em", [], [cbn]},
pct
]}
] ->
{thc, cbn <> pct}
_ ->
{"unknown", "unknown"}
end
[{_, _, [variety]}] =
Floki.find(result, "h4.variety")
|> Floki.find("a")
data = Floki.find(result, "div.description")
description = Floki.find(data, "span")
{_, _, description} = List.last(description)
description =
Enum.map(description, fn x ->
case x do
{_, _, [name]} -> String.replace(name, "“", "") |> String.replace("”", "")
str -> String.replace(str, "“", "") |> String.replace("”", "")
end
end)
|> Enum.join("")
data = Floki.find(result, "div#collapse_positive")
data = Floki.find(data, "div.tags-list")
data = Floki.find(data, "a")
moods =
Enum.map(data, fn x ->
[{_, _, [name]}] = Floki.find(x, "a")
name
end)
data = Floki.find(result, "div#collapse_relieved")
data = Floki.find(data, "div.tags-list")
data = Floki.find(data, "a")
symptoms =
Enum.map(data, fn x ->
[{_, _, [name]}] = Floki.find(x, "a")
name
end)
data = Floki.find(result, "div#collapse_flavors")
data = Floki.find(data, "div.tags-list")
data = Floki.find(data, "a")
flavors =
Enum.map(data, fn x ->
[{_, _, [name]}] = Floki.find(x, "a")
name
end)
data = Floki.find(result, "div#collapse_aromas")
data = Floki.find(data, "div.tags-list")
data = Floki.find(data, "a")
aromas =
Enum.map(data, fn x ->
[{_, _, [name]}] = Floki.find(x, "a")
name
end)
{thc, cbn} = thc
reply = %{
description: description,
name: String.trim(name),
variety: String.trim(variety),
thc: String.replace(thc, "\n", "") |> String.replace(~r/\s+/, " ") |> String.trim(),
cbn: String.replace(cbn, "\n", "") |> String.replace(~r/\s+/, " ") |> String.trim(),
strain_percentages: String.trim(strain_percentages),
moods: moods,
symptoms: symptoms,
flavors: flavors,
aromas: aromas
}
{:ok, reply}
end
end
end