Fix returned visibility of announces in MastodonAPI
[akkoma] / lib / pleroma / web / mastodon_api / controllers / mastodon_api_controller.ex
index 32a58d929258c7f14efdda85fa1bba30d5d0ef5a..80a7b5bef78f86b780276dd99a127552ca672002 100644 (file)
@@ -5,31 +5,22 @@
 defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   use Pleroma.Web, :controller
 
-  import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, truthy_param?: 1]
+  import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
 
-  alias Pleroma.Activity
   alias Pleroma.Bookmark
   alias Pleroma.Config
-  alias Pleroma.Emoji
-  alias Pleroma.HTTP
-  alias Pleroma.Object
   alias Pleroma.Pagination
   alias Pleroma.Plugs.RateLimiter
-  alias Pleroma.Repo
   alias Pleroma.Stats
   alias Pleroma.User
   alias Pleroma.Web
   alias Pleroma.Web.ActivityPub.ActivityPub
-  alias Pleroma.Web.ActivityPub.Visibility
   alias Pleroma.Web.CommonAPI
   alias Pleroma.Web.MastodonAPI.AccountView
-  alias Pleroma.Web.MastodonAPI.AppView
   alias Pleroma.Web.MastodonAPI.MastodonView
   alias Pleroma.Web.MastodonAPI.StatusView
-  alias Pleroma.Web.MediaProxy
   alias Pleroma.Web.OAuth.App
   alias Pleroma.Web.OAuth.Authorization
-  alias Pleroma.Web.OAuth.Scopes
   alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.TwitterAPI.TwitterAPI
 
@@ -37,139 +28,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 
   plug(RateLimiter, :password_reset when action == :password_reset)
 
-  @local_mastodon_name "Mastodon-Local"
-
   action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
 
-  def create_app(conn, params) do
-    scopes = Scopes.fetch_scopes(params, ["read"])
-
-    app_attrs =
-      params
-      |> Map.drop(["scope", "scopes"])
-      |> Map.put("scopes", scopes)
-
-    with cs <- App.register_changeset(%App{}, app_attrs),
-         false <- cs.changes[:client_name] == @local_mastodon_name,
-         {:ok, app} <- Repo.insert(cs) do
-      conn
-      |> put_view(AppView)
-      |> render("show.json", %{app: app})
-    end
-  end
-
-  defp add_if_present(
-         map,
-         params,
-         params_field,
-         map_field,
-         value_function \\ fn x -> {:ok, x} end
-       ) do
-    if Map.has_key?(params, params_field) do
-      case value_function.(params[params_field]) do
-        {:ok, new_value} -> Map.put(map, map_field, new_value)
-        :error -> map
-      end
-    else
-      map
-    end
-  end
-
-  def update_credentials(%{assigns: %{user: user}} = conn, params) do
-    original_user = user
-
-    user_params =
-      %{}
-      |> add_if_present(params, "display_name", :name)
-      |> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
-      |> add_if_present(params, "avatar", :avatar, fn value ->
-        with %Plug.Upload{} <- value,
-             {:ok, object} <- ActivityPub.upload(value, type: :avatar) do
-          {:ok, object.data}
-        else
-          _ -> :error
-        end
-      end)
-
-    emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
-
-    user_info_emojis =
-      user.info
-      |> Map.get(:emoji, [])
-      |> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
-      |> Enum.dedup()
-
-    info_params =
-      [
-        :no_rich_text,
-        :locked,
-        :hide_followers_count,
-        :hide_follows_count,
-        :hide_followers,
-        :hide_follows,
-        :hide_favorites,
-        :show_role,
-        :skip_thread_containment,
-        :discoverable
-      ]
-      |> Enum.reduce(%{}, fn key, acc ->
-        add_if_present(acc, params, to_string(key), key, fn value ->
-          {:ok, truthy_param?(value)}
-        end)
-      end)
-      |> add_if_present(params, "default_scope", :default_scope)
-      |> add_if_present(params, "fields", :fields, fn fields ->
-        fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
-
-        {:ok, fields}
-      end)
-      |> add_if_present(params, "fields", :raw_fields)
-      |> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
-        {:ok, Map.merge(user.info.pleroma_settings_store, value)}
-      end)
-      |> add_if_present(params, "header", :banner, fn value ->
-        with %Plug.Upload{} <- value,
-             {:ok, object} <- ActivityPub.upload(value, type: :banner) do
-          {:ok, object.data}
-        else
-          _ -> :error
-        end
-      end)
-      |> add_if_present(params, "pleroma_background_image", :background, fn value ->
-        with %Plug.Upload{} <- value,
-             {:ok, object} <- ActivityPub.upload(value, type: :background) do
-          {:ok, object.data}
-        else
-          _ -> :error
-        end
-      end)
-      |> Map.put(:emoji, user_info_emojis)
-
-    changeset =
-      user
-      |> User.update_changeset(user_params)
-      |> User.change_info(&User.Info.profile_update(&1, info_params))
-
-    with {:ok, user} <- User.update_and_set_cache(changeset) do
-      if original_user != user, do: CommonAPI.update(user)
-
-      json(
-        conn,
-        AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
-      )
-    else
-      _e -> render_error(conn, :forbidden, "Invalid request")
-    end
-  end
-
-  def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
-    with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
-      conn
-      |> put_view(AppView)
-      |> render("short.json", %{app: app})
-    end
-  end
-
+  @local_mastodon_name "Mastodon-Local"
   @mastodon_api_level "2.7.2"
 
   def masto_instance(conn, _params) do
@@ -222,111 +83,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     json(conn, mastodon_emoji)
   end
 
-  def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
-         true <- Visibility.visible_for_user?(activity, user) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("poll.json", %{object: object, for: user})
-    else
-      error when is_nil(error) or error == false ->
-        render_error(conn, :not_found, "Record not found")
-    end
-  end
-
-  defp get_cached_vote_or_vote(user, object, choices) do
-    idempotency_key = "polls:#{user.id}:#{object.data["id"]}"
-
-    {_, res} =
-      Cachex.fetch(:idempotency_cache, idempotency_key, fn _ ->
-        case CommonAPI.vote(user, object, choices) do
-          {:error, _message} = res -> {:ignore, res}
-          res -> {:commit, res}
-        end
-      end)
-
-    res
-  end
-
-  def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choices}) do
-    with %Object{} = object <- Object.get_by_id(id),
-         true <- object.data["type"] == "Question",
-         %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
-         true <- Visibility.visible_for_user?(activity, user),
-         {:ok, _activities, object} <- get_cached_vote_or_vote(user, object, choices) do
-      conn
-      |> put_view(StatusView)
-      |> try_render("poll.json", %{object: object, for: user})
-    else
-      nil ->
-        render_error(conn, :not_found, "Record not found")
-
-      false ->
-        render_error(conn, :not_found, "Record not found")
-
-      {:error, message} ->
-        conn
-        |> put_status(:unprocessable_entity)
-        |> json(%{error: message})
-    end
-  end
-
-  def update_media(
-        %{assigns: %{user: user}} = conn,
-        %{"id" => id, "description" => description} = _
-      )
-      when is_binary(description) do
-    with %Object{} = object <- Repo.get(Object, id),
-         true <- Object.authorize_mutation(object, user),
-         {:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
-      attachment_data = Map.put(data, "id", object.id)
-
-      conn
-      |> put_view(StatusView)
-      |> render("attachment.json", %{attachment: attachment_data})
-    end
-  end
-
-  def update_media(_conn, _data), do: {:error, :bad_request}
-
-  def upload(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
-    with {:ok, object} <-
-           ActivityPub.upload(
-             file,
-             actor: User.ap_id(user),
-             description: Map.get(data, "description")
-           ) do
-      attachment_data = Map.put(object.data, "id", object.id)
-
-      conn
-      |> put_view(StatusView)
-      |> render("attachment.json", %{attachment: attachment_data})
-    end
-  end
-
-  def set_mascot(%{assigns: %{user: user}} = conn, %{"file" => file}) do
-    with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)),
-         %{} = attachment_data <- Map.put(object.data, "id", object.id),
-         # Reject if not an image
-         %{type: "image"} = rendered <-
-           StatusView.render("attachment.json", %{attachment: attachment_data}) do
-      # Sure!
-      # Save to the user's info
-      {:ok, _user} = User.update_info(user, &User.Info.mascot_update(&1, rendered))
-
-      json(conn, rendered)
-    else
-      %{type: _} -> render_error(conn, :unsupported_media_type, "mascots can only be images")
-    end
-  end
-
-  def get_mascot(%{assigns: %{user: user}} = conn, _params) do
-    mascot = User.get_mascot(user)
-
-    json(conn, mascot)
-  end
-
   def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
     with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
          {_, true} <- {:followed, follower.id != followed.id},
@@ -575,53 +331,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     json(conn, %{})
   end
 
-  def suggestions(%{assigns: %{user: user}} = conn, _) do
-    suggestions = Config.get(:suggestions)
-
-    if Keyword.get(suggestions, :enabled, false) do
-      api = Keyword.get(suggestions, :third_party_engine, "")
-      timeout = Keyword.get(suggestions, :timeout, 5000)
-      limit = Keyword.get(suggestions, :limit, 23)
-
-      host = Config.get([Pleroma.Web.Endpoint, :url, :host])
-
-      user = user.nickname
-
-      url =
-        api
-        |> String.replace("{{host}}", host)
-        |> String.replace("{{user}}", user)
-
-      with {:ok, %{status: 200, body: body}} <-
-             HTTP.get(url, [], adapter: [recv_timeout: timeout, pool: :default]),
-           {:ok, data} <- Jason.decode(body) do
-        data =
-          data
-          |> Enum.slice(0, limit)
-          |> Enum.map(fn x ->
-            x
-            |> Map.put("id", fetch_suggestion_id(x))
-            |> Map.put("avatar", MediaProxy.url(x["avatar"]))
-            |> Map.put("avatar_static", MediaProxy.url(x["avatar_static"]))
-          end)
-
-        json(conn, data)
-      else
-        e ->
-          Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
-      end
-    else
-      json(conn, [])
-    end
-  end
-
-  defp fetch_suggestion_id(attrs) do
-    case User.get_or_fetch(attrs["acct"]) do
-      {:ok, %User{id: id}} -> id
-      _ -> 0
-    end
-  end
-
   def password_reset(conn, params) do
     nickname_or_email = params["email"] || params["nickname"]
 
@@ -638,18 +347,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
-  def try_render(conn, target, params)
-      when is_binary(target) do
-    case render(conn, target, params) do
-      nil -> render_error(conn, :not_implemented, "Can't display this activity")
-      res -> res
-    end
-  end
-
-  def try_render(conn, _, _) do
-    render_error(conn, :not_implemented, "Can't display this activity")
-  end
-
   defp present?(nil), do: false
   defp present?(false), do: false
   defp present?(_), do: true