Merge branch 'feature/fake-statuses' into 'develop'

Add fake status submit

See merge request pleroma/pleroma!995
This commit is contained in:
lambda 2019-04-02 14:17:43 +00:00
commit a79ce94dd4
7 changed files with 141 additions and 27 deletions

View file

@ -44,3 +44,9 @@ Has these additional fields under the `pleroma` object:
Has these additional fields under the `pleroma` object: Has these additional fields under the `pleroma` object:
- `is_seen`: true if the notification was read by the user - `is_seen`: true if the notification was read by the user
## POST `/api/v1/statuses`
Additional parameters can be added to the JSON body:
- `preview`: boolean, if set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.

View file

@ -28,9 +28,13 @@ def filter_tags(html, scrubber), do: Scrubber.scrub(html, scrubber)
def filter_tags(html), do: filter_tags(html, nil) def filter_tags(html), do: filter_tags(html, nil)
def strip_tags(html), do: Scrubber.scrub(html, Scrubber.StripTags) def strip_tags(html), do: Scrubber.scrub(html, Scrubber.StripTags)
# TODO: rename object to activity because that's what it is really working with
def get_cached_scrubbed_html_for_object(content, scrubbers, object, module) do def get_cached_scrubbed_html_for_object(content, scrubbers, object, module) do
key = "#{module}#{generate_scrubber_signature(scrubbers)}|#{object.id}" key = "#{module}#{generate_scrubber_signature(scrubbers)}|#{object.id}"
Cachex.fetch!(:scrubber_cache, key, fn _key -> ensure_scrubbed_html(content, scrubbers) end)
Cachex.fetch!(:scrubber_cache, key, fn _key ->
ensure_scrubbed_html(content, scrubbers, object.data["object"]["fake"] || false)
end)
end end
def get_cached_stripped_html_for_object(content, object, module) do def get_cached_stripped_html_for_object(content, object, module) do
@ -44,11 +48,20 @@ def get_cached_stripped_html_for_object(content, object, module) do
def ensure_scrubbed_html( def ensure_scrubbed_html(
content, content,
scrubbers scrubbers,
false = _fake
) do ) do
{:commit, filter_tags(content, scrubbers)} {:commit, filter_tags(content, scrubbers)}
end end
def ensure_scrubbed_html(
content,
scrubbers,
true = _fake
) do
{:ignore, filter_tags(content, scrubbers)}
end
defp generate_scrubber_signature(scrubber) when is_atom(scrubber) do defp generate_scrubber_signature(scrubber) when is_atom(scrubber) do
generate_scrubber_signature([scrubber]) generate_scrubber_signature([scrubber])
end end

View file

@ -44,6 +44,11 @@ def get_by_ap_id(ap_id) do
# Use this whenever possible, especially when walking graphs in an O(N) loop! # Use this whenever possible, especially when walking graphs in an O(N) loop!
def normalize(%Activity{object: %Object{} = object}), do: object def normalize(%Activity{object: %Object{} = object}), do: object
# A hack for fake activities
def normalize(%Activity{data: %{"object" => %{"fake" => true} = data}}) do
%Object{id: "pleroma:fake_object_id", data: data}
end
# Catch and log Object.normalize() calls where the Activity's child object is not # Catch and log Object.normalize() calls where the Activity's child object is not
# preloaded. # preloaded.
def normalize(%Activity{data: %{"object" => %{"id" => ap_id}}}) do def normalize(%Activity{data: %{"object" => %{"id" => ap_id}}}) do

View file

@ -113,15 +113,15 @@ def decrease_replies_count_if_reply(%Object{
def decrease_replies_count_if_reply(_object), do: :noop def decrease_replies_count_if_reply(_object), do: :noop
def insert(map, local \\ true) when is_map(map) do def insert(map, local \\ true, fake \\ false) when is_map(map) do
with nil <- Activity.normalize(map), with nil <- Activity.normalize(map),
map <- lazy_put_activity_defaults(map), map <- lazy_put_activity_defaults(map, fake),
:ok <- check_actor_is_active(map["actor"]), :ok <- check_actor_is_active(map["actor"]),
{_, true} <- {:remote_limit_error, check_remote_limit(map)}, {_, true} <- {:remote_limit_error, check_remote_limit(map)},
{:ok, map} <- MRF.filter(map), {:ok, map} <- MRF.filter(map),
{recipients, _, _} = get_recipients(map),
{:fake, false, map, recipients} <- {:fake, fake, map, recipients},
{:ok, object} <- insert_full_object(map) do {:ok, object} <- insert_full_object(map) do
{recipients, _, _} = get_recipients(map)
{:ok, activity} = {:ok, activity} =
Repo.insert(%Activity{ Repo.insert(%Activity{
data: map, data: map,
@ -146,8 +146,23 @@ def insert(map, local \\ true) when is_map(map) do
stream_out(activity) stream_out(activity)
{:ok, activity} {:ok, activity}
else else
%Activity{} = activity -> {:ok, activity} %Activity{} = activity ->
error -> {:error, error} {:ok, activity}
{:fake, true, map, recipients} ->
activity = %Activity{
data: map,
local: local,
actor: map["actor"],
recipients: recipients,
id: "pleroma:fakeid"
}
Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
{:ok, activity}
error ->
{:error, error}
end end
end end
@ -190,7 +205,7 @@ def stream_out(activity) do
end end
end end
def create(%{to: to, actor: actor, context: context, object: object} = params) do def create(%{to: to, actor: actor, context: context, object: object} = params, fake \\ false) do
additional = params[:additional] || %{} additional = params[:additional] || %{}
# only accept false as false value # only accept false as false value
local = !(params[:local] == false) local = !(params[:local] == false)
@ -201,13 +216,17 @@ def create(%{to: to, actor: actor, context: context, object: object} = params) d
%{to: to, actor: actor, published: published, context: context, object: object}, %{to: to, actor: actor, published: published, context: context, object: object},
additional additional
), ),
{:ok, activity} <- insert(create_data, local), {:ok, activity} <- insert(create_data, local, fake),
{:fake, false, activity} <- {:fake, fake, activity},
_ <- increase_replies_count_if_reply(create_data), _ <- increase_replies_count_if_reply(create_data),
# Changing note count prior to enqueuing federation task in order to avoid # Changing note count prior to enqueuing federation task in order to avoid
# race conditions on updating user.info # race conditions on updating user.info
{:ok, _actor} <- increase_note_count_if_public(actor, activity), {:ok, _actor} <- increase_note_count_if_public(actor, activity),
:ok <- maybe_federate(activity) do :ok <- maybe_federate(activity) do
{:ok, activity} {:ok, activity}
else
{:fake, true, activity} ->
{:ok, activity}
end end
end end

View file

@ -175,18 +175,26 @@ def maybe_federate(_), do: :ok
Adds an id and a published data if they aren't there, Adds an id and a published data if they aren't there,
also adds it to an included object also adds it to an included object
""" """
def lazy_put_activity_defaults(map) do def lazy_put_activity_defaults(map, fake \\ false) do
map =
unless fake do
%{data: %{"id" => context}, id: context_id} = create_context(map["context"]) %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
map =
map map
|> Map.put_new_lazy("id", &generate_activity_id/0) |> Map.put_new_lazy("id", &generate_activity_id/0)
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &make_date/0)
|> Map.put_new("context", context) |> Map.put_new("context", context)
|> Map.put_new("context_id", context_id) |> Map.put_new("context_id", context_id)
else
map
|> Map.put_new("id", "pleroma:fakeid")
|> Map.put_new_lazy("published", &make_date/0)
|> Map.put_new("context", "pleroma:fakecontext")
|> Map.put_new("context_id", -1)
end
if is_map(map["object"]) do if is_map(map["object"]) do
object = lazy_put_object_defaults(map["object"], map) object = lazy_put_object_defaults(map["object"], map, fake)
%{map | "object" => object} %{map | "object" => object}
else else
map map
@ -196,7 +204,18 @@ def lazy_put_activity_defaults(map) do
@doc """ @doc """
Adds an id and published date if they aren't there. Adds an id and published date if they aren't there.
""" """
def lazy_put_object_defaults(map, activity \\ %{}) do def lazy_put_object_defaults(map, activity \\ %{}, fake)
def lazy_put_object_defaults(map, activity, true = _fake) do
map
|> Map.put_new_lazy("published", &make_date/0)
|> Map.put_new("id", "pleroma:fake_object_id")
|> Map.put_new("context", activity["context"])
|> Map.put_new("fake", true)
|> Map.put_new("context_id", activity["context_id"])
end
def lazy_put_object_defaults(map, activity, _fake) do
map map
|> Map.put_new_lazy("id", &generate_object_id/0) |> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &make_date/0)

View file

@ -172,13 +172,16 @@ def post(user, %{"status" => status} = data) do
end) end)
) do ) do
res = res =
ActivityPub.create(%{ ActivityPub.create(
%{
to: to, to: to,
actor: user, actor: user,
context: context, context: context,
object: object, object: object,
additional: %{"cc" => cc, "directMessage" => visibility == "direct"} additional: %{"cc" => cc, "directMessage" => visibility == "direct"}
}) },
data["preview"] || false
)
res res
end end

View file

@ -143,6 +143,55 @@ test "posting a sensitive status", %{conn: conn} do
assert Activity.get_by_id(id) assert Activity.get_by_id(id)
end end
test "posting a fake status", %{conn: conn} do
user = insert(:user)
real_conn =
conn
|> assign(:user, user)
|> post("/api/v1/statuses", %{
"status" =>
"\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it"
})
real_status = json_response(real_conn, 200)
assert real_status
assert Object.get_by_ap_id(real_status["uri"])
real_status =
real_status
|> Map.put("id", nil)
|> Map.put("url", nil)
|> Map.put("uri", nil)
|> Map.put("created_at", nil)
|> Kernel.put_in(["pleroma", "conversation_id"], nil)
fake_conn =
conn
|> assign(:user, user)
|> post("/api/v1/statuses", %{
"status" =>
"\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it",
"preview" => true
})
fake_status = json_response(fake_conn, 200)
assert fake_status
refute Object.get_by_ap_id(fake_status["uri"])
fake_status =
fake_status
|> Map.put("id", nil)
|> Map.put("url", nil)
|> Map.put("uri", nil)
|> Map.put("created_at", nil)
|> Kernel.put_in(["pleroma", "conversation_id"], nil)
assert real_status == fake_status
end
test "posting a status with OGP link preview", %{conn: conn} do test "posting a status with OGP link preview", %{conn: conn} do
Pleroma.Config.put([:rich_media, :enabled], true) Pleroma.Config.put([:rich_media, :enabled], true)
user = insert(:user) user = insert(:user)