From 454dc1857074c8a98b4fada6d65ed4a810f1c501 Mon Sep 17 00:00:00 2001 From: Roger Braun Date: Sat, 9 Sep 2017 18:09:37 +0200 Subject: [PATCH] Add favoriting to Mastodon API. --- lib/pleroma/web/common_api/common_api.ex | 11 ++++++++++ .../mastodon_api/mastodon_api_controller.ex | 7 +++++++ .../web/mastodon_api/views/status_view.ex | 3 ++- lib/pleroma/web/router.ex | 1 + lib/pleroma/web/twitter_api/twitter_api.ex | 21 +++++++------------ .../web/twitter_api/twitter_api_controller.ex | 9 +++----- .../mastodon_api_controller_test.exs | 14 +++++++++++++ test/web/twitter_api/twitter_api_test.exs | 2 +- 8 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index b1d2172c7..43cec9121 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -22,6 +22,17 @@ def repeat(id_or_ap_id, user) do end end + def favorite(id_or_ap_id, user) do + with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), + false <- activity.data["actor"] == user.ap_id, + object <- Object.get_by_ap_id(activity.data["object"]["id"]) do + ActivityPub.like(user, object) + else + _ -> + {:error, "Could not favorite"} + end + end + # This is a hack for twidere. def get_by_id_or_ap_id(id) do activity = Repo.get(Activity, id) || Activity.get_create_activity_by_object_ap_id(id) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 67b5d49b3..c0ae3fd23 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -87,4 +87,11 @@ def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do render conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity} end end + + def fav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do + with {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.favorite(ap_id_or_id, user), + %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do + render conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity} + end + end end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index d1e5f58c5..7b798506a 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -22,6 +22,7 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity} |> Enum.map(fn (user) -> AccountView.render("mention.json", %{user: user}) end) repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || []) + favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || []) %{ id: activity.id, @@ -36,7 +37,7 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity} reblogs_count: announcement_count, favourites_count: like_count, reblogged: !!repeated, - favourited: false, # fix + favourited: !!favorited, muted: false, sensitive: sensitive, spoiler_text: "", diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 4e59530ae..33b51fd34 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -59,6 +59,7 @@ def user_fetcher(username) do delete "/statuses/:id", MastodonAPIController, :delete_status post "/statuses/:id/reblog", MastodonAPIController, :reblog_status + post "/statuses/:id/favourite", MastodonAPIController, :fav_status end scope "/api", Pleroma.Web do diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index daa53c73b..0c77e092c 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -115,19 +115,6 @@ def unfollow(%User{} = follower, params) do end end - def favorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do - object = Object.get_by_ap_id(object["id"]) - - {:ok, _like_activity, object} = ActivityPub.like(user, object) - new_data = activity.data - |> Map.put("object", object.data) - - status = %{activity | data: new_data} - |> activity_to_status(%{for: user}) - - {:ok, status} - end - def unfavorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do object = Object.get_by_ap_id(object["id"]) @@ -149,6 +136,14 @@ def repeat(%User{} = user, ap_id_or_id) do end end + def fav(%User{} = user, ap_id_or_id) do + with {:ok, _announce, %{data: %{"id" => id}}} = CommonAPI.favorite(ap_id_or_id, user), + %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id), + status <- activity_to_status(activity, %{for: user}) do + {:ok, status} + end + end + def upload(%Plug.Upload{} = file, format \\ "xml") do {:ok, object} = ActivityPub.upload(file) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index a07c60e06..7da1291b0 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -149,12 +149,9 @@ def get_by_id_or_ap_id(id) do end def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do - activity = get_by_id_or_ap_id(id) - {:ok, status} = TwitterAPI.favorite(user, activity) - response = Poison.encode!(status) - - conn - |> json_reply(200, response) + with {:ok, status} <- TwitterAPI.fav(user, id) do + json(conn, status) + end end def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 6cdb75d08..9af49da12 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -135,4 +135,18 @@ test "reblogs and returns the reblogged status", %{conn: conn} do assert activity.id == id end end + + describe "favoriting" do + test "favs a status and returns it", %{conn: conn} do + activity = insert(:note_activity) + user = insert(:user) + + conn = conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/favourite") + + assert %{"id" => id, "favourites_count" => 1, "favourited" => true} = json_response(conn, 200) + assert activity.id == id + end + end end diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index c1c9b2d22..a9494f424 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -264,7 +264,7 @@ test "it favorites a status, returns the updated status" do note_activity = insert(:note_activity) activity_user = Repo.get_by!(User, ap_id: note_activity.data["actor"]) - {:ok, status} = TwitterAPI.favorite(user, note_activity) + {:ok, status} = TwitterAPI.fav(user, note_activity.id) updated_activity = Activity.get_by_ap_id(note_activity.data["id"]) assert status == ActivityRepresenter.to_map(updated_activity, %{user: activity_user, for: user})