akkoma/lib/pleroma/collections/fetcher.ex

87 lines
2.8 KiB
Elixir
Raw Permalink Normal View History

2022-07-03 18:20:59 +00:00
# Akkoma: The cooler fediverse server
# Copyright © 2022- Akkoma Authors <https://akkoma.dev/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Akkoma.Collections.Fetcher do
@moduledoc """
Activitypub Collections fetching functions
see: https://www.w3.org/TR/activitystreams-core/#paging
"""
alias Pleroma.Object.Fetcher
alias Pleroma.Config
2022-07-05 13:45:28 +00:00
require Logger
2022-07-03 18:20:59 +00:00
@spec fetch_collection(String.t() | map()) :: {:ok, [Pleroma.Object.t()]} | {:error, any()}
def fetch_collection(ap_id) when is_binary(ap_id) do
2022-07-03 18:20:59 +00:00
with {:ok, page} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id) do
{:ok, objects_from_collection(page)}
else
e ->
Logger.error("Could not fetch collection #{ap_id} - #{inspect(e)}")
e
2022-07-03 18:20:59 +00:00
end
end
def fetch_collection(%{"type" => type} = page)
when type in ["Collection", "OrderedCollection", "CollectionPage", "OrderedCollectionPage"] do
{:ok, objects_from_collection(page)}
end
2022-07-03 18:20:59 +00:00
defp items_in_page(%{"type" => type, "orderedItems" => items})
when is_list(items) and type in ["OrderedCollection", "OrderedCollectionPage"],
do: items
defp items_in_page(%{"type" => type, "items" => items})
when is_list(items) and type in ["Collection", "CollectionPage"],
do: items
defp objects_from_collection(%{"type" => type, "orderedItems" => items} = page)
when is_list(items) and type in ["OrderedCollection", "OrderedCollectionPage"],
do: maybe_next_page(page, items)
2022-07-03 18:20:59 +00:00
defp objects_from_collection(%{"type" => type, "items" => items} = page)
when is_list(items) and type in ["Collection", "CollectionPage"],
do: maybe_next_page(page, items)
2022-07-03 18:20:59 +00:00
defp objects_from_collection(%{"type" => type, "first" => first})
when is_binary(first) and type in ["Collection", "OrderedCollection"] do
fetch_page_items(first)
end
defp objects_from_collection(%{"type" => type, "first" => %{"id" => id}})
when is_binary(id) and type in ["Collection", "OrderedCollection"] do
fetch_page_items(id)
end
defp objects_from_collection(_page), do: []
2022-07-03 18:20:59 +00:00
defp fetch_page_items(id, items \\ []) do
if Enum.count(items) >= Config.get([:activitypub, :max_collection_objects]) do
items
else
with {:ok, page} <- Fetcher.fetch_and_contain_remote_object_from_id(id) do
objects = items_in_page(page)
2022-07-03 18:20:59 +00:00
if Enum.count(objects) > 0 do
maybe_next_page(page, items ++ objects)
else
items
end
2022-07-03 18:20:59 +00:00
else
{:error, {"Object has been deleted", _, _}} ->
items
{:error, error} ->
Logger.error("Could not fetch page #{id} - #{inspect(error)}")
{:error, error}
2022-07-03 18:20:59 +00:00
end
end
end
defp maybe_next_page(%{"next" => id}, items) when is_binary(id) do
fetch_page_items(id, items)
end
defp maybe_next_page(_, items), do: items
end