From a4db3a732fba1b3f01d875d040bd4587f9c0c5f3 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 2 Apr 2018 14:46:56 +0200 Subject: [PATCH] Pre-fetch conversation ids. --- .../web/twitter_api/views/activity_view.ex | 39 ++++++++++++++++++- .../twitter_api/views/activity_view_test.exs | 26 +++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 3e69af3e3..0c5138503 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -7,9 +7,44 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Repo alias Pleroma.Formatter + import Ecto.Query + + defp query_context_ids(contexts) do + query = from o in Object, + where: fragment("(?)->>'id' = ANY(?)", o.data, ^contexts) + + Repo.all(query) + end + + defp collect_context_ids(activities) do + contexts = activities + |> Enum.map(fn(%{data: data}) -> + data["context"] + end) + |> Enum.filter(&(&1)) + |> query_context_ids() + |> Enum.reduce(%{}, fn(%{data: %{"id" => ap_id}, id: id}, acc) -> + Map.put(acc, ap_id, id) + end) + end + + defp get_context_id(%{data: %{"context" => nil}}), do: nil + defp get_context_id(%{data: %{"context" => context}}, options) do + cond do + id = options[:context_ids][context] -> id + true -> TwitterAPI.context_to_conversation_id(context) + end + end + def render("index.json", opts) do + context_ids = collect_context_ids(opts.activities) + opts = opts + |> Map.put(:context_ids, context_ids) + render_many( opts.activities, ActivityView, @@ -80,7 +115,7 @@ def render("activity.json", %{activity: %{data: %{"type" => "Announce"}} = activ "uri" => "tag:#{activity.data["id"]}:objectType=note", "created_at" => created_at, "retweeted_status" => retweeted_status, - "statusnet_conversation_id" => conversation_id(announced_activity), + "statusnet_conversation_id" => get_context_id(announced_activity, opts), "external_url" => activity.data["id"], "activity_type" => "repeat" } @@ -130,7 +165,7 @@ def render( |> Enum.filter(& &1) |> Enum.map(fn user -> UserView.render("show.json", %{user: user, for: opts[:for]}) end) - conversation_id = conversation_id(activity) + conversation_id = get_context_id(activity, opts) tags = activity.data["object"]["tag"] || [] possibly_sensitive = activity.data["object"]["sensitive"] || Enum.member?(tags, "nsfw") diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs index cb8f60fcf..46ffdef44 100644 --- a/test/web/twitter_api/views/activity_view_test.exs +++ b/test/web/twitter_api/views/activity_view_test.exs @@ -10,7 +10,9 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do alias Pleroma.Activity alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub + import Pleroma.Factory + import Mock test "a create activity with a note" do user = insert(:user) @@ -51,6 +53,30 @@ test "a create activity with a note" do assert result == expected end + test "a list of activities" do + user = insert(:user) + other_user = insert(:user, %{nickname: "shp"}) + {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) + + convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"]) + + mocks = [ + { + TwitterAPI, + [], + [context_to_conversation_id: fn(_) -> false end] + } + ] + + with_mocks mocks do + [result] = ActivityView.render("index.json", activities: [activity]) + + assert result["statusnet_conversation_id"] == convo_id + assert result["user"] + refute called TwitterAPI.context_to_conversation_id(:_) + end + end + test "an activity that is a reply" do user = insert(:user) other_user = insert(:user, %{nickname: "shp"})