summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex22
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex1
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex51
-rw-r--r--test/web/activity_pub/activity_pub_test.exs21
-rw-r--r--test/web/twitter_api/twitter_api_controller_test.exs6
-rw-r--r--test/web/twitter_api/views/activity_view_test.exs26
6 files changed, 110 insertions, 17 deletions
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 16a1d3e97..ac3a57e03 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -45,6 +45,18 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"#{Web.base_url()}/#{type}/#{UUID.generate()}"
end
+ def create_context(context) do
+ context = context || generate_id("contexts")
+ changeset = Object.context_mapping(context)
+
+ case Repo.insert(changeset) do
+ {:ok, object} -> object
+ # This should be solved by an upsert, but it seems ecto
+ # has problems accessing the constraint inside the jsonb.
+ {:error, _} -> Object.get_cached_by_ap_id(context)
+ end
+ end
+
@doc """
Enqueues an activity for federation if it's local
"""
@@ -67,13 +79,17 @@ defmodule Pleroma.Web.ActivityPub.Utils do
also adds it to an included object
"""
def lazy_put_activity_defaults(map) do
+ %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
+
map =
map
|> Map.put_new_lazy("id", &generate_activity_id/0)
|> Map.put_new_lazy("published", &make_date/0)
+ |> Map.put_new("context", context)
+ |> Map.put_new("context_id", context_id)
if is_map(map["object"]) do
- object = lazy_put_object_defaults(map["object"])
+ object = lazy_put_object_defaults(map["object"], map)
%{map | "object" => object}
else
map
@@ -83,10 +99,12 @@ defmodule Pleroma.Web.ActivityPub.Utils do
@doc """
Adds an id and published date if they aren't there.
"""
- def lazy_put_object_defaults(map) do
+ def lazy_put_object_defaults(map, activity \\ %{}) do
map
|> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0)
+ |> Map.put_new("context", activity["context"])
+ |> Map.put_new("context_id", activity["context_id"])
end
@doc """
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 30362ef70..027b97154 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -212,6 +212,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
DateTime.utc_now() |> DateTime.to_iso8601()
end
+ # DEPRECATED mostly, context objects are now created at insertion time.
def context_to_conversation_id(context) do
with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
id
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index 3e69af3e3..760840239 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -7,9 +7,48 @@ 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([]), do: []
+ 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.reject(&(&1.data["context_id"]))
+ |> 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_id" => context_id}}, _) when not is_nil(context_id), do: context_id
+ 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
+ defp get_context_id(_, _), do: nil
+
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 +119,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
"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 +169,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
|> 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")
@@ -174,12 +213,4 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
"possibly_sensitive" => possibly_sensitive
}
end
-
- defp conversation_id(activity) do
- with context when not is_nil(context) <- activity.data["context"] do
- TwitterAPI.context_to_conversation_id(context)
- else
- _e -> nil
- end
- end
end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index cf25abfc1..c6434f789 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -40,12 +40,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
data = %{
"ok" => true,
- "id" => given_id
+ "id" => given_id,
+ "context" => "blabla"
}
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
assert activity.data["ok"] == data["ok"]
assert activity.data["id"] == given_id
+ assert activity.data["context"] == "blabla"
+ assert activity.data["context_id"]
+ end
+
+ test "adds a context when none is there" do
+ data = %{
+ "id" => "some_id",
+ "object" => %{
+ "id" => "object_id"
+ }
+ }
+
+ {:ok, %Activity{} = activity} = ActivityPub.insert(data)
+
+ assert is_binary(activity.data["context"])
+ assert is_binary(activity.data["object"]["context"])
+ assert activity.data["context_id"]
+ assert activity.data["object"]["context_id"]
end
test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index 2cbcfd086..6084381cb 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -160,15 +160,13 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
describe "GET /statusnet/conversation/:id.json" do
test "returns the statuses in the conversation", %{conn: conn} do
{:ok, _user} = UserBuilder.insert()
- {:ok, _activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
+ {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
{:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
{:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
- {:ok, object} = Object.context_mapping("2hu") |> Repo.insert()
-
conn =
conn
- |> get("/api/statusnet/conversation/#{object.id}.json")
+ |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
response = json_response(conn, 200)
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 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest 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"})