+ def make_user_from_ap_id(ap_id) do
+ if user = User.get_by_ap_id(ap_id) do
+ Transmogrifier.upgrade_user_from_ap_id(ap_id)
+ else
+ with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do
+ User.insert_or_update_user(data)
+ else
+ e -> {:error, e}
+ end
+ end
+ end
+
+ def make_user_from_nickname(nickname) do
+ with {:ok, %{"ap_id" => ap_id}} when not is_nil(ap_id) <- WebFinger.finger(nickname) do
+ make_user_from_ap_id(ap_id)
+ else
+ _e -> {:error, "No ap id in webfinger"}
+ end
+ end
+
+ def publish(actor, activity) do
+ followers = if actor.follower_address in activity.recipients do
+ {:ok, followers} = User.get_followers(actor)
+ followers |> Enum.filter(&(!&1.local))
+ else
+ []
+ end
+
+ remote_inboxes = (Pleroma.Web.Salmon.remote_users(activity) ++ followers)
+ |> Enum.filter(fn (user) -> User.ap_enabled?(user) end)
+ |> Enum.map(fn (%{info: %{"source_data" => data}}) ->
+ (data["endpoints"] && data["endpoints"]["sharedInbox"]) || data["inbox"]
+ end)
+ |> Enum.uniq
+
+ {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
+ json = Poison.encode!(data)
+ Enum.each remote_inboxes, fn(inbox) ->
+ Federator.enqueue(:publish_single_ap, %{inbox: inbox, json: json, actor: actor, id: activity.data["id"]})
+ end
+ end
+
+ def publish_one(%{inbox: inbox, json: json, actor: actor, id: id}) do
+ Logger.info("Federating #{id} to #{inbox}")
+ host = URI.parse(inbox).host
+ signature = Pleroma.Web.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)})
+ @httpoison.post(inbox, json, [{"Content-Type", "application/activity+json"}, {"signature", signature}])
+ end
+
+ # TODO:
+ # This will create a Create activity, which we need internally at the moment.
+ def fetch_object_from_id(id) do
+ if object = Object.get_cached_by_ap_id(id) do
+ {:ok, object}
+ else
+ Logger.info("Fetching #{id} via AP")
+ with {:ok, %{body: body, status_code: code}} when code in 200..299 <- @httpoison.get(id, [Accept: "application/activity+json"], follow_redirect: true, timeout: 10000, recv_timeout: 20000),
+ {:ok, data} <- Poison.decode(body),
+ nil <- Object.get_by_ap_id(data["id"]),
+ params <- %{"type" => "Create", "to" => data["to"], "cc" => data["cc"], "actor" => data["attributedTo"], "object" => data},
+ {:ok, activity} <- Transmogrifier.handle_incoming(params) do
+ {:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
+ else
+ object = %Object{} -> {:ok, object}
+ e ->
+ Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
+ case OStatus.fetch_activity_from_url(id) do
+ {:ok, [activity | _]} -> {:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
+ e -> e
+ end
+ end
+ end
+ end
+
+ def is_public?(activity) do
+ "https://www.w3.org/ns/activitystreams#Public" in (activity.data["to"] ++ (activity.data["cc"] || []))
+ end
+
+ def visible_for_user?(activity, nil) do
+ is_public?(activity)
+ end
+ def visible_for_user?(activity, user) do
+ x = [user.ap_id | user.following]
+ y = (activity.data["to"] ++ (activity.data["cc"] || []))
+ visible_for_user?(activity, nil) || Enum.any?(x, &(&1 in y))