1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.User.Synchronization do
9 @spec call([User.t()], map(), keyword()) :: {User.t(), map()}
10 def call(users, errors, opts \\ []) do
11 do_call(users, errors, opts)
14 defp do_call([user | []], errors, opts) do
15 updated = fetch_counters(user, errors, opts)
19 defp do_call([user | others], errors, opts) do
20 updated = fetch_counters(user, errors, opts)
21 do_call(others, updated, opts)
24 defp fetch_counters(user, errors, opts) do
25 %{host: host} = URI.parse(user.ap_id)
28 {following, errors} = fetch_counter(user.ap_id <> "/following", host, errors, opts)
29 info = if following, do: Map.put(info, :following_count, following), else: info
31 {followers, errors} = fetch_counter(user.ap_id <> "/followers", host, errors, opts)
32 info = if followers, do: Map.put(info, :follower_count, followers), else: info
34 User.set_info_cache(user, info)
38 defp available_domain?(domain, errors, opts) do
39 max_retries = Keyword.get(opts, :max_retries, 3)
40 not (Map.has_key?(errors, domain) && errors[domain] >= max_retries)
43 defp fetch_counter(url, host, errors, opts) do
44 with true <- available_domain?(host, errors, opts),
45 {:ok, %{body: body, status: code}} when code in 200..299 <-
48 [{:Accept, "application/activity+json"}]
50 {:ok, data} <- Jason.decode(body) do
51 {data["totalItems"], errors}
57 {nil, Map.update(errors, host, 1, &(&1 + 1))}