diff options
| author | lain <lain@soykaf.club> | 2019-08-02 11:23:07 +0000 | 
|---|---|---|
| committer | lain <lain@soykaf.club> | 2019-08-02 11:23:07 +0000 | 
| commit | 5ff8f07ca906d77a6ec1d5ba912a787f855364f9 (patch) | |
| tree | ff047fd71408e947b91ce9a44fe3fb026e7c684f /lib | |
| parent | 1fe092e03cab11a08e5a15d6bbaf0fd603ef4a00 (diff) | |
| parent | 301ea0dc0466371032f44f3e936d1b951ed9784c (diff) | |
| download | pleroma-5ff8f07ca906d77a6ec1d5ba912a787f855364f9.tar.gz pleroma-5ff8f07ca906d77a6ec1d5ba912a787f855364f9.zip | |
Merge branch 'feature/hide-follows-remote' into 'develop'
Refactor Follows/Followers counter syncronization and set hide_followers/hide_follows for remote users
See merge request pleroma/pleroma!1411
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/object/fetcher.ex | 7 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 91 | ||||
| -rw-r--r-- | lib/pleroma/user/info.ex | 24 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 76 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 33 | 
5 files changed, 171 insertions, 60 deletions
| diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex index 305ce8357..8d79ddb1f 100644 --- a/lib/pleroma/object/fetcher.ex +++ b/lib/pleroma/object/fetcher.ex @@ -114,7 +114,7 @@ defmodule Pleroma.Object.Fetcher do      end    end -  def fetch_and_contain_remote_object_from_id(id) do +  def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do      Logger.info("Fetching object #{id} via AP")      date = @@ -141,4 +141,9 @@ defmodule Pleroma.Object.Fetcher do          {:error, e}      end    end + +  def fetch_and_contain_remote_object_from_id(%{"id" => id}), +    do: fetch_and_contain_remote_object_from_id(id) + +  def fetch_and_contain_remote_object_from_id(_id), do: {:error, "id must be a string"}  end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 1adb82f32..974f96852 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -114,7 +114,9 @@ defmodule Pleroma.User do    def user_info(%User{} = user, args \\ %{}) do      following_count = -      if args[:following_count], do: args[:following_count], else: following_count(user) +      if args[:following_count], +        do: args[:following_count], +        else: user.info.following_count || following_count(user)      follower_count =        if args[:follower_count], do: args[:follower_count], else: user.info.follower_count @@ -406,6 +408,8 @@ defmodule Pleroma.User do          {1, [follower]} = Repo.update_all(q, []) +        follower = maybe_update_following_count(follower) +          {:ok, _} = update_follower_count(followed)          set_cache(follower) @@ -425,6 +429,8 @@ defmodule Pleroma.User do        {1, [follower]} = Repo.update_all(q, []) +      follower = maybe_update_following_count(follower) +        {:ok, followed} = update_follower_count(followed)        set_cache(follower) @@ -709,32 +715,73 @@ defmodule Pleroma.User do      |> update_and_set_cache()    end +  def maybe_fetch_follow_information(user) do +    with {:ok, user} <- fetch_follow_information(user) do +      user +    else +      e -> +        Logger.error("Follower/Following counter update for #{user.ap_id} failed.\n#{inspect(e)}") + +        user +    end +  end + +  def fetch_follow_information(user) do +    with {:ok, info} <- ActivityPub.fetch_follow_information_for_user(user) do +      info_cng = User.Info.follow_information_update(user.info, info) + +      changeset = +        user +        |> change() +        |> put_embed(:info, info_cng) + +      update_and_set_cache(changeset) +    else +      {:error, _} = e -> e +      e -> {:error, e} +    end +  end +    def update_follower_count(%User{} = user) do -    follower_count_query = -      User.Query.build(%{followers: user, deactivated: false}) -      |> select([u], %{count: count(u.id)}) +    if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do +      follower_count_query = +        User.Query.build(%{followers: user, deactivated: false}) +        |> select([u], %{count: count(u.id)}) + +      User +      |> where(id: ^user.id) +      |> join(:inner, [u], s in subquery(follower_count_query)) +      |> update([u, s], +        set: [ +          info: +            fragment( +              "jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)", +              u.info, +              s.count +            ) +        ] +      ) +      |> select([u], u) +      |> Repo.update_all([]) +      |> case do +        {1, [user]} -> set_cache(user) +        _ -> {:error, user} +      end +    else +      {:ok, maybe_fetch_follow_information(user)} +    end +  end -    User -    |> where(id: ^user.id) -    |> join(:inner, [u], s in subquery(follower_count_query)) -    |> update([u, s], -      set: [ -        info: -          fragment( -            "jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)", -            u.info, -            s.count -          ) -      ] -    ) -    |> select([u], u) -    |> Repo.update_all([]) -    |> case do -      {1, [user]} -> set_cache(user) -      _ -> {:error, user} +  def maybe_update_following_count(%User{local: false} = user) do +    if Pleroma.Config.get([:instance, :external_user_synchronization]) do +      {:ok, maybe_fetch_follow_information(user)} +    else +      user      end    end +  def maybe_update_following_count(user), do: user +    def remove_duplicated_following(%User{following: following} = user) do      uniq_following = Enum.uniq(following) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 9beb3ddbd..b03e705c3 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -16,6 +16,8 @@ defmodule Pleroma.User.Info do      field(:source_data, :map, default: %{})      field(:note_count, :integer, default: 0)      field(:follower_count, :integer, default: 0) +    # Should be filled in only for remote users +    field(:following_count, :integer, default: nil)      field(:locked, :boolean, default: false)      field(:confirmation_pending, :boolean, default: false)      field(:confirmation_token, :string, default: nil) @@ -223,7 +225,11 @@ defmodule Pleroma.User.Info do        :uri,        :hub,        :topic, -      :salmon +      :salmon, +      :hide_followers, +      :hide_follows, +      :follower_count, +      :following_count      ])    end @@ -234,7 +240,11 @@ defmodule Pleroma.User.Info do        :source_data,        :banner,        :locked, -      :magic_key +      :magic_key, +      :follower_count, +      :following_count, +      :hide_follows, +      :hide_followers      ])    end @@ -348,4 +358,14 @@ defmodule Pleroma.User.Info do      cast(info, params, [:muted_reblogs])    end + +  def follow_information_update(info, params) do +    info +    |> cast(params, [ +      :hide_followers, +      :hide_follows, +      :follower_count, +      :following_count +    ]) +  end  end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 6fd7fef92..07a65127b 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1009,10 +1009,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      user_data = %{        ap_id: data["id"],        info: %{ -        "ap_enabled" => true, -        "source_data" => data, -        "banner" => banner, -        "locked" => locked +        ap_enabled: true, +        source_data: data, +        banner: banner, +        locked: locked        },        avatar: avatar,        name: data["name"], @@ -1036,6 +1036,71 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      {:ok, user_data}    end +  def fetch_follow_information_for_user(user) do +    with {:ok, following_data} <- +           Fetcher.fetch_and_contain_remote_object_from_id(user.following_address), +         following_count when is_integer(following_count) <- following_data["totalItems"], +         {:ok, hide_follows} <- collection_private(following_data), +         {:ok, followers_data} <- +           Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address), +         followers_count when is_integer(followers_count) <- followers_data["totalItems"], +         {:ok, hide_followers} <- collection_private(followers_data) do +      {:ok, +       %{ +         hide_follows: hide_follows, +         follower_count: followers_count, +         following_count: following_count, +         hide_followers: hide_followers +       }} +    else +      {:error, _} = e -> +        e + +      e -> +        {:error, e} +    end +  end + +  defp maybe_update_follow_information(data) do +    with {:enabled, true} <- +           {:enabled, Pleroma.Config.get([:instance, :external_user_synchronization])}, +         {:ok, info} <- fetch_follow_information_for_user(data) do +      info = Map.merge(data.info, info) +      Map.put(data, :info, info) +    else +      {:enabled, false} -> +        data + +      e -> +        Logger.error( +          "Follower/Following counter update for #{data.ap_id} failed.\n" <> inspect(e) +        ) + +        data +    end +  end + +  defp collection_private(data) do +    if is_map(data["first"]) and +         data["first"]["type"] in ["CollectionPage", "OrderedCollectionPage"] do +      {:ok, false} +    else +      with {:ok, %{"type" => type}} when type in ["CollectionPage", "OrderedCollectionPage"] <- +             Fetcher.fetch_and_contain_remote_object_from_id(data["first"]) do +        {:ok, false} +      else +        {:error, {:ok, %{status: code}}} when code in [401, 403] -> +          {:ok, true} + +        {:error, _} = e -> +          e + +        e -> +          {:error, e} +      end +    end +  end +    def user_data_from_user_object(data) do      with {:ok, data} <- MRF.filter(data),           {:ok, data} <- object_to_user_data(data) do @@ -1047,7 +1112,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    def fetch_and_prepare_user_from_ap_id(ap_id) do      with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id), -         {:ok, data} <- user_data_from_user_object(data) do +         {:ok, data} <- user_data_from_user_object(data), +         data <- maybe_update_follow_information(data) do        {:ok, data}      else        e -> Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}") diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 44bb1cb9a..5403b71d8 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -608,13 +608,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do        {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) -      banner = new_user_data[:info]["banner"] -      locked = new_user_data[:info]["locked"] || false +      banner = new_user_data[:info][:banner] +      locked = new_user_data[:info][:locked] || false        update_data =          new_user_data          |> Map.take([:name, :bio, :avatar]) -        |> Map.put(:info, %{"banner" => banner, "locked" => locked}) +        |> Map.put(:info, %{banner: banner, locked: locked})        actor        |> User.upgrade_changeset(update_data) @@ -1076,10 +1076,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do          PleromaJobQueue.enqueue(:transmogrifier, __MODULE__, [:user_upgrade, user])        end -      if Pleroma.Config.get([:instance, :external_user_synchronization]) do -        update_following_followers_counters(user) -      end -        {:ok, user}      else        %User{} = user -> {:ok, user} @@ -1112,27 +1108,4 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      data      |> maybe_fix_user_url    end - -  def update_following_followers_counters(user) do -    info = %{} - -    following = fetch_counter(user.following_address) -    info = if following, do: Map.put(info, :following_count, following), else: info - -    followers = fetch_counter(user.follower_address) -    info = if followers, do: Map.put(info, :follower_count, followers), else: info - -    User.set_info_cache(user, info) -  end - -  defp fetch_counter(url) do -    with {:ok, %{body: body, status: code}} when code in 200..299 <- -           Pleroma.HTTP.get( -             url, -             [{:Accept, "application/activity+json"}] -           ), -         {:ok, data} <- Jason.decode(body) do -      data["totalItems"] -    end -  end  end | 
