Introduce new ingestion pipeline structure, implement internal Likes with it.
This commit is contained in:
parent
e3b4a3e96b
commit
6e4f52f8a2
|
@ -18,6 +18,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
alias Pleroma.Web.ActivityPub.MRF
|
alias Pleroma.Web.ActivityPub.MRF
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||||
|
alias Pleroma.Web.ActivityPub.SideEffects
|
||||||
alias Pleroma.Web.Streamer
|
alias Pleroma.Web.Streamer
|
||||||
alias Pleroma.Web.WebFinger
|
alias Pleroma.Web.WebFinger
|
||||||
alias Pleroma.Workers.BackgroundWorker
|
alias Pleroma.Workers.BackgroundWorker
|
||||||
|
@ -123,6 +125,38 @@ def increase_poll_votes_if_vote(%{
|
||||||
|
|
||||||
def increase_poll_votes_if_vote(_create_data), do: :noop
|
def increase_poll_votes_if_vote(_create_data), do: :noop
|
||||||
|
|
||||||
|
@spec common_pipeline(map(), keyword()) :: {:ok, Activity.t(), keyword()} | {:error, any()}
|
||||||
|
def common_pipeline(object, meta) do
|
||||||
|
with {_, {:ok, validated_object, meta}} <-
|
||||||
|
{:validate_object, ObjectValidator.validate(object, meta)},
|
||||||
|
{_, {:ok, mrfd_object}} <- {:mrf_object, MRF.filter(validated_object)},
|
||||||
|
{_, {:ok, %Activity{} = activity, meta}} <-
|
||||||
|
{:persist_object, persist(mrfd_object, meta)},
|
||||||
|
{_, {:ok, %Activity{} = activity, meta}} <-
|
||||||
|
{:execute_side_effects, SideEffects.handle(activity, meta)} do
|
||||||
|
{:ok, activity, meta}
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO rewrite in with style
|
||||||
|
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
|
||||||
|
def persist(object, meta) do
|
||||||
|
local = Keyword.get(meta, :local)
|
||||||
|
{recipients, _, _} = get_recipients(object)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
Repo.insert(%Activity{
|
||||||
|
data: object,
|
||||||
|
local: local,
|
||||||
|
recipients: recipients,
|
||||||
|
actor: object["actor"]
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, activity, meta}
|
||||||
|
end
|
||||||
|
|
||||||
def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do
|
def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when is_map(map) do
|
||||||
with nil <- Activity.normalize(map),
|
with nil <- Activity.normalize(map),
|
||||||
map <- lazy_put_activity_defaults(map, fake),
|
map <- lazy_put_activity_defaults(map, fake),
|
||||||
|
@ -130,6 +164,7 @@ def insert(map, local \\ true, fake \\ false, bypass_actor_check \\ false) when
|
||||||
{_, 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),
|
{recipients, _, _} = get_recipients(map),
|
||||||
|
# ???
|
||||||
{:fake, false, map, recipients} <- {:fake, fake, map, recipients},
|
{:fake, false, map, recipients} <- {:fake, fake, map, recipients},
|
||||||
:ok <- Containment.contain_child(map),
|
:ok <- Containment.contain_child(map),
|
||||||
{:ok, map, object} <- insert_full_object(map) do
|
{:ok, map, object} <- insert_full_object(map) do
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.Builder do
|
||||||
|
@moduledoc """
|
||||||
|
This module builds the objects. Meant to be used for creating local objects.
|
||||||
|
|
||||||
|
This module encodes our addressing policies and general shape of our objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Object
|
||||||
|
|
||||||
|
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
|
||||||
|
def like(actor, object) do
|
||||||
|
object_actor = User.get_cached_by_ap_id(object.data["actor"])
|
||||||
|
|
||||||
|
# Address the actor of the object, and our actor's follower collection if the post is public.
|
||||||
|
to =
|
||||||
|
if Visibility.is_public?(object) do
|
||||||
|
[actor.follower_address, object.data["actor"]]
|
||||||
|
else
|
||||||
|
[object.data["actor"]]
|
||||||
|
end
|
||||||
|
|
||||||
|
# CC everyone who's been addressed in the object, except ourself and the object actor's
|
||||||
|
# follower collection
|
||||||
|
cc =
|
||||||
|
(object.data["to"] ++ (object.data["cc"] || []))
|
||||||
|
|> List.delete(actor.ap_id)
|
||||||
|
|> List.delete(object_actor.follower_address)
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
%{
|
||||||
|
"id" => Utils.generate_activity_id(),
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Like",
|
||||||
|
"object" => object.data["id"],
|
||||||
|
"to" => to,
|
||||||
|
"cc" => cc,
|
||||||
|
"context" => object.data["context"]
|
||||||
|
}, []}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||||
|
@moduledoc """
|
||||||
|
This module is responsible for validating an object (which can be an activity)
|
||||||
|
and checking if it is both well formed and also compatible with our view of
|
||||||
|
the system.
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
|
||||||
|
def validate_id(object, meta) do
|
||||||
|
with {_, true} <- {:id_presence, Map.has_key?(object, "id")} do
|
||||||
|
{:ok, object, meta}
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_actor(object, meta) do
|
||||||
|
with {_, %User{}} <- {:actor_validation, User.get_cached_by_ap_id(object["actor"])} do
|
||||||
|
{:ok, object, meta}
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def common_validations(object, meta) do
|
||||||
|
with {_, {:ok, object, meta}} <- {:validate_id, validate_id(object, meta)},
|
||||||
|
{_, {:ok, object, meta}} <- {:validate_actor, validate_actor(object, meta)} do
|
||||||
|
{:ok, object, meta}
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||||
|
def validate(object, meta)
|
||||||
|
|
||||||
|
def validate(%{"type" => "Like"} = object, meta) do
|
||||||
|
with {:ok, object, meta} <- common_validations(object, meta),
|
||||||
|
{_, %Object{} = liked_object} <- {:find_liked_object, Object.normalize(object["object"])},
|
||||||
|
{_, nil} <- {:existing_like, Utils.get_existing_like(object["actor"], liked_object)} do
|
||||||
|
{:ok, object, meta}
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate(object, meta) do
|
||||||
|
common_validations(object, meta)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.SideEffects do
|
||||||
|
@moduledoc """
|
||||||
|
This module looks at an inserted object and executes the side effects that it
|
||||||
|
implies. For example, a `Like` activity will increase the like count on the
|
||||||
|
liked object, a `Follow` activity will add the user to the follower
|
||||||
|
collection, and so on.
|
||||||
|
"""
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Notification
|
||||||
|
|
||||||
|
def handle(object, meta \\ [])
|
||||||
|
|
||||||
|
# Tasks this handles:
|
||||||
|
# - Add like to object
|
||||||
|
# - Set up notification
|
||||||
|
def handle(%{data: %{"type" => "Like"}} = object, meta) do
|
||||||
|
liked_object = Object.get_by_ap_id(object.data["object"])
|
||||||
|
Utils.add_like_to_object(object, liked_object)
|
||||||
|
Notification.create_notifications(object)
|
||||||
|
{:ok, object, meta}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Nothing to do
|
||||||
|
def handle(object, meta) do
|
||||||
|
{:ok, object, meta}
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
alias Pleroma.ThreadMute
|
alias Pleroma.ThreadMute
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.Builder
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
import Pleroma.Web.CommonAPI.Utils
|
import Pleroma.Web.CommonAPI.Utils
|
||||||
|
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
require Logger
|
||||||
|
|
||||||
def follow(follower, followed) do
|
def follow(follower, followed) do
|
||||||
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
|
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
|
||||||
|
@ -98,16 +100,31 @@ def unrepeat(id_or_ap_id, user) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def favorite(id_or_ap_id, user) do
|
@spec favorite(User.t(), binary()) :: {:ok, Activity.t()} | {:error, any()}
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
def favorite(%User{} = user, id) do
|
||||||
object <- Object.normalize(activity),
|
with {_, %Activity{object: object}} <- {:find_object, Activity.get_by_id_with_object(id)},
|
||||||
nil <- Utils.get_existing_like(user.ap_id, object) do
|
{_, {:ok, like_object, meta}} <- {:build_object, Builder.like(user, object)},
|
||||||
ActivityPub.like(user, object)
|
{_, {:ok, %Activity{} = activity, _meta}} <-
|
||||||
|
{:common_pipeline,
|
||||||
|
ActivityPub.common_pipeline(like_object, Keyword.put(meta, :local, true))} do
|
||||||
|
{:ok, activity}
|
||||||
else
|
else
|
||||||
_ -> {:error, dgettext("errors", "Could not favorite")}
|
e ->
|
||||||
|
Logger.error("Could not favorite #{id}. Error: #{inspect(e, pretty: true)}")
|
||||||
|
{:error, dgettext("errors", "Could not favorite")}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# def favorite(id_or_ap_id, user) do
|
||||||
|
# with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||||
|
# object <- Object.normalize(activity),
|
||||||
|
# nil <- Utils.get_existing_like(user.ap_id, object) do
|
||||||
|
# ActivityPub.like(user, object)
|
||||||
|
# else
|
||||||
|
# _ -> {:error, dgettext("errors", "Could not favorite")}
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
def unfavorite(id_or_ap_id, user) do
|
def unfavorite(id_or_ap_id, user) do
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
|
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
|
@ -201,9 +201,9 @@ def unreblog(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "POST /api/v1/statuses/:id/favourite"
|
@doc "POST /api/v1/statuses/:id/favourite"
|
||||||
def favourite(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
def favourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
||||||
with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),
|
with {:ok, _fav} <- CommonAPI.favorite(user, activity_id),
|
||||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
|
%Activity{} = activity <- Activity.get_by_id(activity_id) do
|
||||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -431,7 +431,7 @@ test "it does not send notification to mentioned users in likes" do
|
||||||
"status" => "hey @#{other_user.nickname}!"
|
"status" => "hey @#{other_user.nickname}!"
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user)
|
{:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
|
||||||
|
|
||||||
assert other_user not in Notification.get_notified_from_activity(activity_two)
|
assert other_user not in Notification.get_notified_from_activity(activity_two)
|
||||||
end
|
end
|
||||||
|
@ -461,7 +461,7 @@ test "liking an activity results in 1 notification, then 0 if the activity is de
|
||||||
|
|
||||||
assert Enum.empty?(Notification.for_user(user))
|
assert Enum.empty?(Notification.for_user(user))
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
assert length(Notification.for_user(user)) == 1
|
assert length(Notification.for_user(user)) == 1
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ test "liking an activity results in 1 notification, then 0 if the activity is un
|
||||||
|
|
||||||
assert Enum.empty?(Notification.for_user(user))
|
assert Enum.empty?(Notification.for_user(user))
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
assert length(Notification.for_user(user)) == 1
|
assert length(Notification.for_user(user)) == 1
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ test "liking an activity which is already deleted does not generate a notificati
|
||||||
|
|
||||||
assert Enum.empty?(Notification.for_user(user))
|
assert Enum.empty?(Notification.for_user(user))
|
||||||
|
|
||||||
{:error, _} = CommonAPI.favorite(activity.id, other_user)
|
{:error, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
assert Enum.empty?(Notification.for_user(user))
|
assert Enum.empty?(Notification.for_user(user))
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,7 +182,8 @@ test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||||
{:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
|
{:ok, activity} = CommonAPI.favorite(user, activity.id)
|
||||||
|
object = Object.get_by_ap_id(activity.data["object"])
|
||||||
|
|
||||||
assert object.data["like_count"] == 1
|
assert object.data["like_count"] == 1
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ test "it turns OrderedCollection likes into empty arrays" do
|
||||||
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})
|
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})
|
||||||
{:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"})
|
{:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"})
|
||||||
|
|
||||||
CommonAPI.favorite(id, user2)
|
CommonAPI.favorite(user2, id)
|
||||||
|
|
||||||
likes = %{
|
likes = %{
|
||||||
"first" =>
|
"first" =>
|
||||||
|
|
|
@ -1059,8 +1059,8 @@ test "it deletes a user, all follow relationships and all activities", %{user: u
|
||||||
object_two = insert(:note, user: follower)
|
object_two = insert(:note, user: follower)
|
||||||
activity_two = insert(:note_activity, user: follower, note: object_two)
|
activity_two = insert(:note_activity, user: follower, note: object_two)
|
||||||
|
|
||||||
{:ok, like, _} = CommonAPI.favorite(activity_two.id, user)
|
{:ok, like} = CommonAPI.favorite(user, activity_two.id)
|
||||||
{:ok, like_two, _} = CommonAPI.favorite(activity.id, follower)
|
{:ok, like_two} = CommonAPI.favorite(follower, activity.id)
|
||||||
{:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
|
{:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
|
||||||
|
|
||||||
{:ok, job} = User.delete(user)
|
{:ok, job} = User.delete(user)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
describe "likes" do
|
||||||
|
test "it is well formed" do
|
||||||
|
_required_fields = [
|
||||||
|
"id",
|
||||||
|
"actor",
|
||||||
|
"object"
|
||||||
|
]
|
||||||
|
|
||||||
|
_user = insert(:user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.ActivityPub.Builder
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.SideEffects
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
describe "like objects" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, post} = CommonAPI.post(user, %{"status" => "hey"})
|
||||||
|
|
||||||
|
{:ok, like_data, _meta} = Builder.like(user, post.object)
|
||||||
|
{:ok, like, _meta} = ActivityPub.persist(like_data, [])
|
||||||
|
|
||||||
|
%{like: like, user: user}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "add the like to the original object", %{like: like, user: user} do
|
||||||
|
{:ok, like, _} = SideEffects.handle(like)
|
||||||
|
object = Object.get_by_ap_id(like.data["object"])
|
||||||
|
assert object.data["like_count"] == 1
|
||||||
|
assert user.ap_id in object.data["likes"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1187,7 +1187,7 @@ test "it translates ostatus IDs to external URLs" do
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity, _} = CommonAPI.favorite(referent_activity.id, user)
|
{:ok, activity} = CommonAPI.favorite(user, referent_activity.id)
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
|
|
||||||
assert modified["object"] == "http://gs.example.org:4040/index.php/notice/29"
|
assert modified["object"] == "http://gs.example.org:4040/index.php/notice/29"
|
||||||
|
|
|
@ -41,7 +41,7 @@ test "renders a like activity" do
|
||||||
object = Object.normalize(note)
|
object = Object.normalize(note)
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, like_activity, _} = CommonAPI.favorite(note.id, user)
|
{:ok, like_activity} = CommonAPI.favorite(user, note.id)
|
||||||
|
|
||||||
result = ObjectView.render("object.json", %{object: like_activity})
|
result = ObjectView.render("object.json", %{object: like_activity})
|
||||||
|
|
||||||
|
|
|
@ -251,9 +251,12 @@ test "favoriting a status" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
|
{:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
|
||||||
|
|
||||||
{:ok, %Activity{}, _} = CommonAPI.favorite(activity.id, user)
|
{:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
|
||||||
|
assert data["type"] == "Like"
|
||||||
|
assert data["actor"] == user.ap_id
|
||||||
|
assert data["object"] == post_activity.data["object"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "retweeting a status twice returns an error" do
|
test "retweeting a status twice returns an error" do
|
||||||
|
@ -270,8 +273,8 @@ test "favoriting a status twice returns an error" do
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
|
||||||
{:ok, %Activity{}, _object} = CommonAPI.favorite(activity.id, user)
|
{:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
|
||||||
{:error, _} = CommonAPI.favorite(activity.id, user)
|
{:error, _} = CommonAPI.favorite(user, activity.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ test "filters notifications using exclude_types", %{conn: conn} do
|
||||||
|
|
||||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
|
{:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
|
||||||
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
||||||
{:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
|
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||||
{:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
|
{:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
|
||||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
|
|
|
@ -589,7 +589,7 @@ test "reblogged status for another user", %{conn: conn} do
|
||||||
user1 = insert(:user)
|
user1 = insert(:user)
|
||||||
user2 = insert(:user)
|
user2 = insert(:user)
|
||||||
user3 = insert(:user)
|
user3 = insert(:user)
|
||||||
CommonAPI.favorite(activity.id, user2)
|
{:ok, _} = CommonAPI.favorite(user2, activity.id)
|
||||||
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
|
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
|
||||||
{:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
|
{:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
|
||||||
{:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
|
{:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
|
||||||
|
@ -695,7 +695,7 @@ test "unfavorites a status and returns it", %{conn: conn} do
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, user)
|
{:ok, _} = CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
@ -1047,7 +1047,7 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c
|
||||||
|
|
||||||
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -1078,7 +1078,7 @@ test "does not return users who have favorited the status but are blocked", %{
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, user} = User.block(user, other_user)
|
{:ok, user} = User.block(user, other_user)
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -1091,7 +1091,7 @@ test "does not return users who have favorited the status but are blocked", %{
|
||||||
|
|
||||||
test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do
|
test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -1112,7 +1112,7 @@ test "requires authentification for private posts", %{conn: conn, user: user} do
|
||||||
"visibility" => "direct"
|
"visibility" => "direct"
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> assign(:user, nil)
|
|> assign(:user, nil)
|
||||||
|
@ -1269,7 +1269,7 @@ test "returns the favorites of a user", %{conn: conn} do
|
||||||
{:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
|
{:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
|
||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(activity.id, user)
|
{:ok, _} = CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
first_conn =
|
first_conn =
|
||||||
conn
|
conn
|
||||||
|
@ -1289,7 +1289,7 @@ test "returns the favorites of a user", %{conn: conn} do
|
||||||
"Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
|
"Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
|
{:ok, _} = CommonAPI.favorite(user, second_activity.id)
|
||||||
|
|
||||||
last_like = status["id"]
|
last_like = status["id"]
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ test "Favourite notification" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
another_user = insert(:user)
|
another_user = insert(:user)
|
||||||
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
{:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
|
||||||
{:ok, favorite_activity, _object} = CommonAPI.favorite(create_activity.id, another_user)
|
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
|
||||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||||
create_activity = Activity.get_by_id(create_activity.id)
|
create_activity = Activity.get_by_id(create_activity.id)
|
||||||
|
|
||||||
|
|
|
@ -271,7 +271,7 @@ test "only gets a notice in AS2 format for Create messages", %{conn: conn} do
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
|
{:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
|
||||||
url = "/notice/#{like_activity.id}"
|
url = "/notice/#{like_activity.id}"
|
||||||
|
|
||||||
assert like_activity.data["type"] == "Like"
|
assert like_activity.data["type"] == "Like"
|
||||||
|
@ -298,7 +298,7 @@ test "render html for redirect for html format", %{conn: conn} do
|
||||||
|
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
|
{:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
|
||||||
|
|
||||||
assert like_activity.data["type"] == "Like"
|
assert like_activity.data["type"] == "Like"
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ test "returns list of statuses favorited by specified user", %{
|
||||||
user: user
|
user: user
|
||||||
} do
|
} do
|
||||||
[activity | _] = insert_pair(:note_activity)
|
[activity | _] = insert_pair(:note_activity)
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -184,7 +184,7 @@ test "returns favorites for specified user_id when user is not logged in", %{
|
||||||
user: user
|
user: user
|
||||||
} do
|
} do
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -205,7 +205,7 @@ test "returns favorited DM only when user is logged in and he is one of recipien
|
||||||
"visibility" => "direct"
|
"visibility" => "direct"
|
||||||
})
|
})
|
||||||
|
|
||||||
CommonAPI.favorite(direct.id, user)
|
CommonAPI.favorite(user, direct.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -236,7 +236,7 @@ test "does not return others' favorited DM when user is not one of recipients",
|
||||||
"visibility" => "direct"
|
"visibility" => "direct"
|
||||||
})
|
})
|
||||||
|
|
||||||
CommonAPI.favorite(direct.id, user)
|
CommonAPI.favorite(user, direct.id)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -255,7 +255,7 @@ test "paginates favorites using since_id and max_id", %{
|
||||||
activities = insert_list(10, :note_activity)
|
activities = insert_list(10, :note_activity)
|
||||||
|
|
||||||
Enum.each(activities, fn activity ->
|
Enum.each(activities, fn activity ->
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
third_activity = Enum.at(activities, 2)
|
third_activity = Enum.at(activities, 2)
|
||||||
|
@ -283,7 +283,7 @@ test "limits favorites using limit parameter", %{
|
||||||
7
|
7
|
||||||
|> insert_list(:note_activity)
|
|> insert_list(:note_activity)
|
||||||
|> Enum.each(fn activity ->
|
|> Enum.each(fn activity ->
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
|
@ -321,7 +321,7 @@ test "returns 403 error when user has hidden own favorites", %{
|
||||||
} do
|
} do
|
||||||
user = insert(:user, %{info: %{hide_favorites: true}})
|
user = insert(:user, %{info: %{hide_favorites: true}})
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
@ -334,7 +334,7 @@ test "returns 403 error when user has hidden own favorites", %{
|
||||||
test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
|
test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
CommonAPI.favorite(activity.id, user)
|
CommonAPI.favorite(user, activity.id)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -152,7 +152,7 @@ test "renders body for like activity" do
|
||||||
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
|
"<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, activity, _} = CommonAPI.favorite(activity.id, user)
|
{:ok, activity} = CommonAPI.favorite(user, activity.id)
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post"
|
assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post"
|
||||||
|
|
|
@ -68,7 +68,7 @@ test "it doesn't send notify to the 'user:notification' stream when a user is bl
|
||||||
)
|
)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
|
||||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, blocked)
|
{:ok, notif} = CommonAPI.favorite(blocked, activity.id)
|
||||||
|
|
||||||
Streamer.stream("user:notification", notif)
|
Streamer.stream("user:notification", notif)
|
||||||
Task.await(task)
|
Task.await(task)
|
||||||
|
@ -87,7 +87,7 @@ test "it doesn't send notify to the 'user:notification' stream when a thread is
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||||
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
||||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
{:ok, notif} = CommonAPI.favorite(user2, activity.id)
|
||||||
Streamer.stream("user:notification", notif)
|
Streamer.stream("user:notification", notif)
|
||||||
Task.await(task)
|
Task.await(task)
|
||||||
end
|
end
|
||||||
|
@ -105,7 +105,7 @@ test "it doesn't send notify to the 'user:notification' stream' when a domain is
|
||||||
|
|
||||||
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
|
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
{:ok, notif} = CommonAPI.favorite(user2, activity.id)
|
||||||
|
|
||||||
Streamer.stream("user:notification", notif)
|
Streamer.stream("user:notification", notif)
|
||||||
Task.await(task)
|
Task.await(task)
|
||||||
|
|
Loading…
Reference in New Issue