defmodule BazVenueAdapterOpenSea.FetchCollectionAssetPageBySlug do
@moduledoc """
Implementation of the Baz.VenueAdapter.fetch_collection_asset_page_by_slug/4 callback
"""
defmodule Input do
defstruct ~w[slug token_ids page_cursor page_limit]a
end
alias BazVenueAdapterOpenSea.Credentials
alias BazVenueAdapterOpenSea.ApiClient
@type venue :: Baz.VenueAdapter.venue()
@type slug :: Baz.VenueAdapter.collection_slug()
@type token_ids :: Baz.VenueAdapter.token_ids()
@type page_cursor :: Baz.Page.cursor()
@type result :: Baz.VenueAdapter.fetch_collection_asset_page_by_slug_result()
@default_page_limit 200
@spec fetch_collection_asset_page_by_slug(venue, slug, token_ids, page_cursor) :: result
def fetch_collection_asset_page_by_slug(venue, slug, token_ids, page_cursor) do
input = %Input{
slug: slug,
token_ids: token_ids,
page_cursor: page_cursor,
page_limit: @default_page_limit
}
{venue, input}
|> with_api_key()
|> fetch()
|> write_to_raw_sinks()
|> build_changset()
end
defp with_api_key({venue, input}) do
case Credentials.get_api_key(venue.credentials) do
{:ok, api_key} -> {venue, input, api_key}
{:error, :not_found} -> {:error, :api_key_not_found}
end
end
defp fetch({venue, input, api_key}) do
params = build_params(input)
api_result = ApiClient.fetch_collection_asset_page_by_slug(params, api_key)
{venue, input, api_key, api_result}
end
defp fetch({:error, _reason} = error), do: error
defp write_to_raw_sinks({venue, input, _api_key, api_result} = args) do
:ok = Baz.Sinks.write_raw(:collection_assets, venue, input, api_result)
args
end
defp write_to_raw_sinks({:error, _reason} = error), do: error
defp build_changset({venue, input, _api_key, api_result}) do
case api_result do
{:ok, cursor, _} ->
assets = build_assets(venue, input.slug, cursor)
%Baz.Page{data: assets, next_page_cursor: cursor.next}
{:error, reason, _} ->
{:error, reason}
end
end
defp build_changset({:error, _reason} = error), do: error
defp build_params(input) do
p = %{collection_slug: input.slug, limit: input.page_limit}
p = if input.token_ids != nil, do: Map.put(p, :token_ids, input.token_ids), else: p
if input.page_cursor != nil, do: Map.put(p, :cursor, input.page_cursor), else: p
end
defp build_assets(venue, slug, cursor) do
cursor.assets
|> Enum.map(fn venue_asset ->
{venue, slug, venue_asset}
|> build_asset_attrs()
|> Baz.CollectionAssets.collection_asset_changeset()
end)
end
defp build_asset_attrs({venue, slug, venue_asset}) do
# TODO: enumerate collection asset traits and save
%{
venue: venue.name,
slug: slug,
token_id: venue_asset.token_id,
name: venue_asset.name,
background_color: venue_asset.background_color,
image_uri: venue_asset.image_url,
image_preview_uri: venue_asset.image_preview_url,
image_thumbnail_uri: venue_asset.image_thumbnail_url,
image_original_uri: venue_asset.image_original_url,
animation_uri: venue_asset.animation_url,
animation_original_uri: venue_asset.animation_original_url,
is_nsfw: venue_asset.is_nsfw
}
end
end