Merge remote-tracking branch 'upstream/develop' into admin-create-users
[akkoma] / lib / pleroma / object / fetcher.ex
1 defmodule Pleroma.Object.Fetcher do
2 alias Pleroma.HTTP
3 alias Pleroma.Object
4 alias Pleroma.Object.Containment
5 alias Pleroma.Web.ActivityPub.Transmogrifier
6 alias Pleroma.Web.OStatus
7
8 require Logger
9
10 defp reinject_object(data) do
11 Logger.debug("Reinjecting object #{data["id"]}")
12
13 with data <- Transmogrifier.fix_object(data),
14 {:ok, object} <- Object.create(data) do
15 {:ok, object}
16 else
17 e ->
18 Logger.error("Error while processing object: #{inspect(e)}")
19 {:error, e}
20 end
21 end
22
23 # TODO:
24 # This will create a Create activity, which we need internally at the moment.
25 def fetch_object_from_id(id) do
26 if object = Object.get_cached_by_ap_id(id) do
27 {:ok, object}
28 else
29 Logger.info("Fetching #{id} via AP")
30
31 with {:ok, data} <- fetch_and_contain_remote_object_from_id(id),
32 nil <- Object.normalize(data, false),
33 params <- %{
34 "type" => "Create",
35 "to" => data["to"],
36 "cc" => data["cc"],
37 "actor" => data["actor"] || data["attributedTo"],
38 "object" => data
39 },
40 :ok <- Containment.contain_origin(id, params),
41 {:ok, activity} <- Transmogrifier.handle_incoming(params),
42 {:object, _data, %Object{} = object} <-
43 {:object, data, Object.normalize(activity, false)} do
44 {:ok, object}
45 else
46 {:error, {:reject, nil}} ->
47 {:reject, nil}
48
49 {:object, data, nil} ->
50 reinject_object(data)
51
52 object = %Object{} ->
53 {:ok, object}
54
55 _e ->
56 Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
57
58 case OStatus.fetch_activity_from_url(id) do
59 {:ok, [activity | _]} -> {:ok, Object.normalize(activity, false)}
60 e -> e
61 end
62 end
63 end
64 end
65
66 def fetch_object_from_id!(id) do
67 with {:ok, object} <- fetch_object_from_id(id) do
68 object
69 else
70 _e ->
71 nil
72 end
73 end
74
75 def fetch_and_contain_remote_object_from_id(id) do
76 Logger.info("Fetching object #{id} via AP")
77
78 with true <- String.starts_with?(id, "http"),
79 {:ok, %{body: body, status: code}} when code in 200..299 <-
80 HTTP.get(
81 id,
82 [{:Accept, "application/activity+json"}]
83 ),
84 {:ok, data} <- Jason.decode(body),
85 :ok <- Containment.contain_origin_from_id(id, data) do
86 {:ok, data}
87 else
88 e ->
89 {:error, e}
90 end
91 end
92 end