aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEgor Kislitsyn <egor@kislitsyn.com>2019-05-13 16:15:14 +0700
committerEgor Kislitsyn <egor@kislitsyn.com>2019-05-13 16:15:14 +0700
commit23276e8d6848fa8eae390c16b6e0619c12546e4a (patch)
tree200d1c78015dd09f2f977eb1442a862e514ea4e5 /lib
parenta3dc02d282f886d3b4842ec70976cfa84f2e4099 (diff)
downloadpleroma-23276e8d6848fa8eae390c16b6e0619c12546e4a.tar.gz
Use pseudo ap id of a list in BCC
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/list.ex32
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex46
-rw-r--r--lib/pleroma/web/common_api/common_api.ex8
-rw-r--r--lib/pleroma/web/common_api/utils.ex11
-rw-r--r--lib/pleroma/web/salmon/salmon.ex19
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)