From 1eb7318831e7239ec929457f6298fb05cb461b43 Mon Sep 17 00:00:00 2001 From: sxsdv1 Date: Sat, 12 Jan 2019 17:52:30 +0100 Subject: Prepare all types objects before serialising Activities returned from inbox can include other types of objects like Article --- lib/pleroma/web/activity_pub/transmogrifier.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 87b7fc07f..b0f8c59cc 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -641,7 +641,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # internal -> Mastodon # """ - def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do + def prepare_outgoing(%{"type" => "Create", "object" => object} = data) do object = object |> prepare_object -- cgit v1.2.3 From 36711e1c83bb24a2b104c4a8f384c475c1583638 Mon Sep 17 00:00:00 2001 From: sxsdv1 Date: Tue, 8 Jan 2019 19:22:26 +0100 Subject: Handle client submitted activitypub like activity --- lib/pleroma/web/activity_pub/activity_pub_controller.ex | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 73ca07e84..6bc8b7195 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -204,6 +204,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do end end + def handle_user_activity(user, %{"type" => "Like"} = params) do + with %Object{} = object <- Object.normalize(params["object"]), + {:ok, activity, _object} <- ActivityPub.like(user, object) do + {:ok, activity} + else + _ -> {:error, "Can't like object"} + end + end + def handle_user_activity(_, _) do {:error, "Unhandled activity type"} end -- cgit v1.2.3 From 581edd5a91189e6fb2a94a277b96f9c8197617b8 Mon Sep 17 00:00:00 2001 From: sxsdv1 Date: Fri, 11 Jan 2019 23:34:32 +0100 Subject: Add route to get object like activities --- .../web/activity_pub/activity_pub_controller.ex | 30 +++++++++++++++++++ lib/pleroma/web/activity_pub/utils.ex | 21 +++++++++++++ lib/pleroma/web/activity_pub/views/object_view.ex | 34 ++++++++++++++++++++++ lib/pleroma/web/router.ex | 1 + 4 files changed, 86 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 6bc8b7195..7eed0a600 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -54,6 +54,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do end end + def object_likes(conn, %{"uuid" => uuid, "page" => page}) do + with ap_id <- o_status_url(conn, :object, uuid), + %Object{} = object <- Object.get_cached_by_ap_id(ap_id), + {_, true} <- {:public?, ActivityPub.is_public?(object)}, + likes <- Utils.get_object_likes(object) do + {page, _} = Integer.parse(page) + + conn + |> put_resp_header("content-type", "application/activity+json") + |> json(ObjectView.render("likes.json", ap_id, likes, page)) + else + {:public?, false} -> + {:error, :not_found} + end + end + + def object_likes(conn, %{"uuid" => uuid}) do + with ap_id <- o_status_url(conn, :object, uuid), + %Object{} = object <- Object.get_cached_by_ap_id(ap_id), + {_, true} <- {:public?, ActivityPub.is_public?(object)}, + likes <- Utils.get_object_likes(object) do + conn + |> put_resp_header("content-type", "application/activity+json") + |> json(ObjectView.render("likes.json", ap_id, likes)) + else + {:public?, false} -> + {:error, :not_found} + end + end + def activity(conn, %{"uuid" => uuid}) do with ap_id <- o_status_url(conn, :activity, uuid), %Activity{} = activity <- Activity.normalize(ap_id), diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index b313996db..6ecab773c 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -231,6 +231,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do Repo.one(query) end + @doc """ + Returns like activities targeting an object + """ + def get_object_likes(%{data: %{"id" => id}}) do + query = + from( + activity in Activity, + # this is to use the index + where: + fragment( + "coalesce((?)->'object'->>'id', (?)->>'object') = ?", + activity.data, + activity.data, + ^id + ), + where: fragment("(?)->>'type' = 'Like'", activity.data) + ) + + Repo.all(query) + end + def make_like_data(%User{ap_id: ap_id} = actor, %{data: %{"id" => id}} = object, activity_id) do data = %{ "type" => "Like", diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index b5c9bf8d0..193042056 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -35,4 +35,38 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do Map.merge(base, additional) end + + def render("likes.json", ap_id, likes, page) do + collection(likes, "#{ap_id}/likes", page) + |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) + end + + def render("likes.json", ap_id, likes) do + %{ + "id" => "#{ap_id}/likes", + "type" => "OrderedCollection", + "totalItems" => length(likes), + "first" => collection(likes, "#{ap_id}/followers", 1) + } + |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header()) + end + + def collection(collection, iri, page) do + offset = (page - 1) * 10 + items = Enum.slice(collection, offset, 10) + items = Enum.map(items, fn object -> Transmogrifier.prepare_object(object.data) end) + total = length(collection) + + map = %{ + "id" => "#{iri}?page=#{page}", + "type" => "OrderedCollectionPage", + "partOf" => iri, + "totalItems" => total, + "orderedItems" => items + } + + if offset < total do + Map.put(map, "next", "#{iri}?page=#{page + 1}") + end + end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a5f4d8126..7a0c9fd25 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -421,6 +421,7 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/followers", ActivityPubController, :followers) get("/users/:nickname/following", ActivityPubController, :following) get("/users/:nickname/outbox", ActivityPubController, :outbox) + get("/objects/:uuid/likes", ActivityPubController, :object_likes) end pipeline :activitypub_client do -- cgit v1.2.3 From 868034375c5122175f872967e49559dafed9403c Mon Sep 17 00:00:00 2001 From: sxsdv1 Date: Wed, 9 Jan 2019 09:22:00 +0100 Subject: Add likes to activitypub object representation Top level of the likes OrderedCollection is inlined to get immediate access to totalItems. Because the count can be returned without scanning the database for like activities the extra query is saved when the client only wants to display the total. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index b0f8c59cc..86d11c874 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -629,6 +629,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> add_mention_tags |> add_emoji_tags |> add_attributed_to + |> add_likes |> prepare_attachments |> set_conversation |> set_reply_to_uri @@ -788,6 +789,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("attributedTo", attributedTo) end + def add_likes(%{"id" => id, "like_count" => likes} = object) do + likes = %{ + "id" => "#{id}/likes", + "first" => "#{id}/likes?page=1", + "type" => "OrderedCollection", + "totalItems" => likes + } + + object + |> Map.put("likes", likes) + end + + def add_likes(object) do + object + end + def prepare_attachments(object) do attachments = (object["attachment"] || []) @@ -803,7 +820,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do defp strip_internal_fields(object) do object |> Map.drop([ - "likes", "like_count", "announcements", "announcement_count", -- cgit v1.2.3