diff options
| author | Egor Kislitsyn <egor@kislitsyn.com> | 2019-05-13 16:15:14 +0700 | 
|---|---|---|
| committer | Egor Kislitsyn <egor@kislitsyn.com> | 2019-05-13 16:15:14 +0700 | 
| commit | 23276e8d6848fa8eae390c16b6e0619c12546e4a (patch) | |
| tree | 200d1c78015dd09f2f977eb1442a862e514ea4e5 | |
| parent | a3dc02d282f886d3b4842ec70976cfa84f2e4099 (diff) | |
| download | pleroma-23276e8d6848fa8eae390c16b6e0619c12546e4a.tar.gz pleroma-23276e8d6848fa8eae390c16b6e0619c12546e4a.zip | |
Use pseudo ap id of a list in BCC
| -rw-r--r-- | lib/pleroma/list.ex | 32 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 46 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 8 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/web/salmon/salmon.ex | 19 | 
5 files changed, 92 insertions, 24 deletions
| diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex index a5b1cad68..81b842e9c 100644 --- a/lib/pleroma/list.ex +++ b/lib/pleroma/list.ex @@ -12,6 +12,8 @@ defmodule Pleroma.List do    alias Pleroma.Repo    alias Pleroma.User +  @ap_id_regex ~r/^\/users\/(?<nickname>\w+)\/lists\/(?<list_id>\d+)/ +    schema "lists" do      belongs_to(:user, User, type: Pleroma.FlakeId)      field(:title, :string) @@ -32,6 +34,12 @@ defmodule Pleroma.List do      |> validate_required([:following])    end +  def ap_id(%User{nickname: nickname}, list_id) do +    Pleroma.Web.Endpoint.url() <> "/users/#{nickname}/lists/#{list_id}" +  end + +  def ap_id({nickname, list_id}), do: ap_id(%User{nickname: nickname}, list_id) +    def for_user(user, _opts) do      query =        from( @@ -55,6 +63,19 @@ defmodule Pleroma.List do      Repo.one(query)    end +  def get_by_ap_id(ap_id) do +    host = Pleroma.Web.Endpoint.host() + +    with %{host: ^host, path: path} <- URI.parse(ap_id), +         %{"list_id" => list_id, "nickname" => nickname} <- +           Regex.named_captures(@ap_id_regex, path), +         %User{} = user <- User.get_cached_by_nickname(nickname) do +      get(list_id, user) +    else +      _ -> nil +    end +  end +    def get_following(%Pleroma.List{following: following} = _list) do      q =        from( @@ -125,4 +146,15 @@ defmodule Pleroma.List do      |> follow_changeset(attrs)      |> Repo.update()    end + +  def memberships(%User{follower_address: follower_address}) do +    Pleroma.List +    |> where([l], ^follower_address in l.following) +    |> join(:inner, [l], u in User, on: l.user_id == u.id) +    |> select([l, u], {u.nickname, l.id}) +    |> Repo.all() +    |> Enum.map(&ap_id/1) +  end + +  def memberships(_), do: []  end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 84d7f47b1..3b71e0369 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -783,9 +783,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    end    def fetch_activities_query(recipients, opts \\ %{}) do -    base_query = from(activity in Activity) - -    base_query +    Activity      |> maybe_preload_objects(opts)      |> restrict_recipients(recipients, opts["user"])      |> restrict_tag(opts) @@ -807,9 +805,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    end    def fetch_activities(recipients, opts \\ %{}) do -    fetch_activities_query(recipients, opts) +    list_memberships = Pleroma.List.memberships(opts["user"]) + +    fetch_activities_query(recipients ++ list_memberships, opts)      |> Pagination.fetch_paginated(opts)      |> Enum.reverse() +    |> maybe_update_cc(list_memberships, opts["user"]) +  end + +  defp maybe_update_cc(activities, [], _), do: activities +  defp maybe_update_cc(activities, _, nil), do: activities + +  defp maybe_update_cc(activities, list_memberships, user) do +    Enum.map(activities, fn +      %{data: %{"bcc" => bcc}} = activity when is_list(bcc) -> +        if Enum.any?(bcc, &(&1 in list_memberships)) do +          update_in(activity.data["cc"], &[user.ap_id | &1]) +        else +          activity +        end + +      activity -> +        activity +    end)    end    def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do @@ -917,13 +935,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    end    defp recipients(actor, activity) do -    Pleroma.Web.Salmon.remote_users(activity) ++ +    followers =        if actor.follower_address in activity.recipients do          {:ok, followers} = User.get_followers(actor) -        followers |> Enum.filter(&(!&1.local)) +        Enum.filter(followers, &(!&1.local))        else          []        end + +    Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers +  end + +  defp get_cc_ap_ids(ap_id, recipients) do +    host = Map.get(URI.parse(ap_id), :host) + +    recipients +    |> Enum.filter(fn %User{ap_id: ap_id} -> Map.get(URI.parse(ap_id), :host) == host end) +    |> Enum.map(& &1.ap_id)    end    def publish(actor, %{data: %{"bcc" => bcc}} = activity) when is_list(bcc) and bcc != [] do @@ -938,12 +966,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)      |> Instances.filter_reachable()      |> Enum.each(fn {inbox, unreachable_since} -> -      %User{ap_id: cc} = +      %User{ap_id: ap_id} =          Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end) +      cc = get_cc_ap_ids(ap_id, recipients) +        json =          data -        |> Map.put("cc", [cc]) +        |> Map.put("cc", cc)          |> Map.put("directMessage", true)          |> Jason.encode!() diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 4ca59110f..d47d5788c 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -153,7 +153,7 @@ defmodule Pleroma.Web.CommonAPI do               visibility             ),           {to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility), -         {:ok, bcc} <- bcc_for_list(user, visibility), +         bcc <- bcc_for_list(user, visibility),           context <- make_context(in_reply_to),           cw <- data["spoiler_text"],           full_payload <- String.trim(status <> (data["spoiler_text"] || "")), @@ -197,7 +197,7 @@ defmodule Pleroma.Web.CommonAPI do      user =        with emoji <- emoji_from_profile(user),             source_data <- (user.info.source_data || %{}) |> Map.put("tag", emoji), -           info_cng <- Pleroma.User.Info.set_source_data(user.info, source_data), +           info_cng <- User.Info.set_source_data(user.info, source_data),             change <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng),             {:ok, user} <- User.update_and_set_cache(change) do          user @@ -230,7 +230,7 @@ defmodule Pleroma.Web.CommonAPI do           } = activity <- get_by_id_or_ap_id(id_or_ap_id),           true <- Enum.member?(object_to, "https://www.w3.org/ns/activitystreams#Public"),           %{valid?: true} = info_changeset <- -           Pleroma.User.Info.add_pinnned_activity(user.info, activity), +           User.Info.add_pinnned_activity(user.info, activity),           changeset <-             Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),           {:ok, _user} <- User.update_and_set_cache(changeset) do @@ -247,7 +247,7 @@ defmodule Pleroma.Web.CommonAPI do    def unpin(id_or_ap_id, user) do      with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),           %{valid?: true} = info_changeset <- -           Pleroma.User.Info.remove_pinnned_activity(user.info, activity), +           User.Info.remove_pinnned_activity(user.info, activity),           changeset <-             Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),           {:ok, _user} <- User.update_and_set_cache(changeset) do diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 83a745b58..32c3b4b98 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -8,7 +8,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do    alias Pleroma.Activity    alias Pleroma.Config    alias Pleroma.Formatter -  alias Pleroma.List    alias Pleroma.Object    alias Pleroma.Repo    alias Pleroma.User @@ -106,16 +105,10 @@ defmodule Pleroma.Web.CommonAPI.Utils do    def to_for_user_and_mentions(_user, _mentions, _inReplyTo, _), do: {[], []}    def bcc_for_list(user, {:list, list_id}) do -    with {_, %List{} = list} <- {:list, List.get(list_id, user)}, -         {:ok, following} <- List.get_following(list) do -      {:ok, Enum.map(following, & &1.ap_id)} -    else -      {:list, _} -> {:error, "List not found"} -      err -> err -    end +    [Pleroma.List.ap_id(user, list_id)]    end -  def bcc_for_list(_, _), do: {:ok, []} +  def bcc_for_list(_, _), do: []    def make_content_html(          status, diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex index 4d89f4bdb..ca51255f3 100644 --- a/lib/pleroma/web/salmon/salmon.ex +++ b/lib/pleroma/web/salmon/salmon.ex @@ -156,9 +156,22 @@ defmodule Pleroma.Web.Salmon do      {:ok, salmon}    end -  def remote_users(%{data: %{"to" => to} = data}) do +  def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do      cc = Map.get(data, "cc", []) -    bcc = Map.get(data, "bcc", []) + +    bcc = +      data +      |> Map.get("bcc", []) +      |> Enum.reduce([], fn ap_id, bcc -> +        case Pleroma.List.get_by_ap_id(ap_id) do +          %Pleroma.List{user_id: ^user_id} = list -> +            {:ok, following} = Pleroma.List.get_following(list) +            bcc ++ Enum.map(following, & &1.ap_id) + +          _ -> +            bcc +        end +      end)      [to, cc, bcc]      |> Enum.concat() @@ -220,7 +233,7 @@ defmodule Pleroma.Web.Salmon do        {:ok, private, _} = keys_from_pem(keys)        {:ok, feed} = encode(private, feed) -      remote_users = remote_users(activity) +      remote_users = remote_users(user, activity)        salmon_urls = Enum.map(remote_users, & &1.info.salmon)        reachable_urls_metadata = Instances.filter_reachable(salmon_urls) | 
