Packages

A Last.fm API client for Elixir.

Current section

Files

Jump to
lastex lib lastex page.ex
Raw

lib/lastex/page.ex

defmodule Lastex.Page do
@moduledoc """
Pagination wrapper for Last.fm list endpoints.
"""
defstruct [:data, :page, :per_page, :total, :total_pages]
@doc """
Builds a Page from a standard list response.
Takes `{wrapper_key, data_path}` where `data_path` is a string key or list of
string keys to extract the data list from within the wrapper.
Pagination fields are parsed from `wrapper["@attr"]`.
"""
def from_response({:ok, body}, {wrapper_key, data_path}) do
wrapper = body[wrapper_key]
attrs = wrapper["@attr"] || %{}
data_path = List.wrap(data_path)
{:ok,
%__MODULE__{
data: get_in(wrapper, data_path) || [],
page: parse_int(attrs["page"], 1),
per_page: parse_int(attrs["perPage"], 50),
total: parse_int(attrs["total"], 0),
total_pages: parse_int(attrs["totalPages"], 0)
}}
end
def from_response(error, _keys), do: error
@doc """
Builds a Page from a search response.
Search responses nest data under `results > matches_key > data_key` and store
pagination in opensearch fields at the `results` level.
"""
def from_search_response({:ok, body}, {matches_key, data_key}) do
results = body["results"]
per_page = parse_int(results["opensearch:itemsPerPage"], 30)
total = parse_int(results["opensearch:totalResults"], 0)
start_index = parse_int(results["opensearch:startIndex"], 0)
{:ok,
%__MODULE__{
data: get_in(results, [matches_key, data_key]) || [],
page: if(per_page > 0, do: div(start_index, per_page) + 1, else: 1),
per_page: per_page,
total: total,
total_pages: if(per_page > 0, do: ceil(total / per_page), else: 0)
}}
end
def from_search_response(error, _keys), do: error
defp parse_int(nil, default), do: default
defp parse_int(val, _default) when is_integer(val), do: val
defp parse_int(val, default) when is_binary(val) do
case Integer.parse(val) do
{int, _} -> int
:error -> default
end
end
end