From: Egor Kislitsyn Date: Tue, 4 Jun 2019 09:28:23 +0000 (+0700) Subject: Merge remote-tracking branch 'pleroma/develop' into feature/addressable-lists X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=9ce928d8238877f870e099cb2fe010d322717856;p=akkoma Merge remote-tracking branch 'pleroma/develop' into feature/addressable-lists --- 9ce928d8238877f870e099cb2fe010d322717856 diff --cc CHANGELOG.md index b8907a23f,8586ea8a0..99b42e280 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@@ -45,7 -49,7 +49,8 @@@ The format is based on [Keep a Changelo - OAuth: added job to clean expired access tokens - MRF: Support for rejecting reports from specific instances (`mrf_simple`) - MRF: Support for stripping avatars and banner images from specific instances (`mrf_simple`) + - MRF: Support for running subchains. +- Addressable lists ### Changed - **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer diff --cc lib/pleroma/web/activity_pub/activity_pub.ex index 48aaabe94,45feae25a..47115aa6e --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@@ -881,34 -892,23 +889,43 @@@ defmodule Pleroma.Web.ActivityPub.Activ 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, list_memberships, %User{ap_id: user_ap_id}) + when is_list(list_memberships) and length(list_memberships) > 0 do + Enum.map(activities, fn + %{data: %{"bcc" => bcc}} = activity when is_list(bcc) and length(bcc) > 0 -> + 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 + defp maybe_update_cc(activities, _, _), do: activities + - def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do + def fetch_activities_bounded_query(query, recipients, recipients_with_public) do + from(activity in query, + where: + fragment("? && ?", activity.recipients, ^recipients) or + (fragment("? && ?", activity.recipients, ^recipients_with_public) and + "https://www.w3.org/ns/activitystreams#Public" in activity.recipients) + ) + end + + def fetch_activities_bounded(recipients, recipients_with_public, opts \\ %{}) do fetch_activities_query([], opts) - |> restrict_to_cc(recipients_to, recipients_cc) + |> fetch_activities_bounded_query(recipients, recipients_with_public) |> Pagination.fetch_paginated(opts) |> Enum.reverse() end diff --cc lib/pleroma/web/common_api/common_api.ex index e8199200e,5212d5ce5..85fb32669 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@@ -159,8 -201,8 +206,9 @@@ defmodule Pleroma.Web.CommonAPI d data, visibility ), + {poll, poll_emoji} <- make_poll_data(data), {to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility), + bcc <- bcc_for_list(user, visibility), context <- make_context(in_reply_to), cw <- data["spoiler_text"] || "", sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}), @@@ -183,18 -226,21 +232,18 @@@ Map.put( object, "emoji", - Formatter.get_emoji_map(full_payload) + Map.merge(Formatter.get_emoji_map(full_payload), poll_emoji) ) do - res = - ActivityPub.create( - %{ - to: to, - actor: user, - context: context, - object: object, - additional: %{"cc" => cc, "directMessage" => visibility == "direct"} - }, - Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false - ) - - res + ActivityPub.create( + %{ + to: to, + actor: user, + context: context, + object: object, + additional: %{"cc" => cc, "bcc" => bcc, "directMessage" => visibility == "direct"} + }, + Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false + ) else e -> {:error, e} end diff --cc lib/pleroma/web/common_api/utils.ex index d97a80dd5,f35ed36ab..9c92c6cea --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@@ -102,15 -102,72 +102,81 @@@ defmodule Pleroma.Web.CommonAPI.Utils d end end + def to_for_user_and_mentions(_user, _mentions, _inReplyTo, _), do: {[], []} + + def bcc_for_list(user, {:list, list_id}) do + list = Pleroma.List.get(list_id, user) + [list.ap_id] + end + + def bcc_for_list(_, _), do: [] + + def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data) + when is_list(options) do + %{max_expiration: max_expiration, min_expiration: min_expiration} = + limits = Pleroma.Config.get([:instance, :poll_limits]) + + # XXX: There is probably a cleaner way of doing this + try do + # In some cases mastofe sends out strings instead of integers + expires_in = if is_binary(expires_in), do: String.to_integer(expires_in), else: expires_in + + if Enum.count(options) > limits.max_options do + raise ArgumentError, message: "Poll can't contain more than #{limits.max_options} options" + end + + {poll, emoji} = + Enum.map_reduce(options, %{}, fn option, emoji -> + if String.length(option) > limits.max_option_chars do + raise ArgumentError, + message: + "Poll options cannot be longer than #{limits.max_option_chars} characters each" + end + + {%{ + "name" => option, + "type" => "Note", + "replies" => %{"type" => "Collection", "totalItems" => 0} + }, Map.merge(emoji, Formatter.get_emoji_map(option))} + end) + + case expires_in do + expires_in when expires_in > max_expiration -> + raise ArgumentError, message: "Expiration date is too far in the future" + + expires_in when expires_in < min_expiration -> + raise ArgumentError, message: "Expiration date is too soon" + + _ -> + :noop + end + + end_time = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(expires_in) + |> NaiveDateTime.to_iso8601() + + poll = + if Pleroma.Web.ControllerHelper.truthy_param?(data["poll"]["multiple"]) do + %{"type" => "Question", "anyOf" => poll, "closed" => end_time} + else + %{"type" => "Question", "oneOf" => poll, "closed" => end_time} + end + + {poll, emoji} + rescue + e in ArgumentError -> e.message + end + end + + def make_poll_data(%{"poll" => poll}) when is_map(poll) do + "Invalid poll" + end + + def make_poll_data(_data) do + {%{}, %{}} + end + def make_content_html( status, attachments,