Merge remote-tracking branch 'origin' into validate-user-info
[akkoma] / lib / pleroma / web / twitter_api / twitter_api_controller.ex
index 83d725f13987da91f6807a3586c934fc613563b2..b0bd98dbc7bb406a9bb71aa9262a36b83041c07f 100644 (file)
@@ -126,6 +126,19 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     |> render(ActivityView, "index.json", %{activities: activities, for: user})
   end
 
+  def dm_timeline(%{assigns: %{user: user}} = conn, params) do
+    query =
+      ActivityPub.fetch_activities_query(
+        [user.ap_id],
+        Map.merge(params, %{"type" => "Create", "user" => user, visibility: "direct"})
+      )
+
+    activities = Repo.all(query)
+
+    conn
+    |> render(ActivityView, "index.json", %{activities: activities, for: user})
+  end
+
   def notifications(%{assigns: %{user: user}} = conn, params) do
     notifications = Notification.for_user(user, params)
 
@@ -133,6 +146,19 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     |> render(NotificationView, "notification.json", %{notifications: notifications, for: user})
   end
 
+  def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest_id} = params) do
+    Notification.set_read_up_to(user, latest_id)
+
+    notifications = Notification.for_user(user, params)
+
+    conn
+    |> render(NotificationView, "notification.json", %{notifications: notifications, for: user})
+  end
+
+  def notifications_read(%{assigns: %{user: user}} = conn, _) do
+    bad_request_reply(conn, "You need to specify latest_id")
+  end
+
   def follow(%{assigns: %{user: user}} = conn, params) do
     case TwitterAPI.follow(user, params) do
       {:ok, user, followed, _activity} ->
@@ -324,20 +350,6 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     end
   end
 
-  def update_most_recent_notification(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with id when is_number(id) <- String.to_integer(id),
-         info <- user.info,
-         mrn <- max(id, user.info["most_recent_notification"] || 0),
-         updated_info <- Map.put(info, "most_recent_notification", mrn),
-         changeset <- User.info_changeset(user, %{info: updated_info}),
-         {:ok, _user} <- User.update_and_set_cache(changeset) do
-      conn
-      |> json_reply(200, Jason.encode!(mrn))
-    else
-      _e -> bad_request_reply(conn, "Can't update.")
-    end
-  end
-
   def followers(conn, params) do
     with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
          {:ok, followers} <- User.get_followers(user) do
@@ -425,67 +437,52 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     json(conn, [])
   end
 
-  def update_profile(%{assigns: %{user: user}} = conn, params) do
-    params =
-      if bio = params["description"] do
-        mentions = Formatter.parse_mentions(bio)
-        tags = Formatter.parse_tags(bio)
-
-        emoji =
-          (user.info["source_data"]["tag"] || [])
-          |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
-          |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
-            {String.trim(name, ":"), url}
-          end)
-
-        bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
-        Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
-      else
-        params
-      end
-
-    user =
-      if locked = params["locked"] do
-        with locked <- locked == "true",
-             new_info <- Map.put(user.info, "locked", locked),
-             change <- User.info_changeset(user, %{info: new_info}),
-             {:ok, user} <- User.update_and_set_cache(change) do
-          user
+  defp build_info_cng(user, params) do
+    info_params =
+      ["no_rich_text", "locked"]
+      |> Enum.reduce(%{}, fn key, res ->
+        if value = params[key] do
+          Map.put(res, key, value == "true")
         else
-          _e -> user
+          res
         end
-      else
-        user
-      end
+      end)
 
-    user =
-      if no_rich_text = params["no_rich_text"] do
-        with no_rich_text <- no_rich_text == "true",
-             new_info <- Map.put(user.info, "no_rich_text", no_rich_text),
-             change <- User.info_changeset(user, %{info: new_info}),
-             {:ok, user} <- User.update_and_set_cache(change) do
-          user
-        else
-          _e -> user
-        end
+    info_params =
+      if value = params["default_scope"] do
+        Map.put(info_params, "default_scope", value)
       else
-        user
+        info_params
       end
 
-    user =
-      if default_scope = params["default_scope"] do
-        with new_info <- Map.put(user.info, "default_scope", default_scope),
-             change <- User.info_changeset(user, %{info: new_info}),
-             {:ok, user} <- User.update_and_set_cache(change) do
-          user
-        else
-          _e -> user
-        end
-      else
-        user
-      end
+    User.Info.profile_update(user.info, info_params)
+  end
+
+  defp add_profile_emoji(user, params) do
+    if bio = params["description"] do
+      mentions = Formatter.parse_mentions(bio)
+      tags = Formatter.parse_tags(bio)
+
+      emoji =
+        (user.info.source_data["tag"] || [])
+        |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
+        |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
+          {String.trim(name, ":"), url}
+        end)
+
+      bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
+      Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
+    else
+      params
+    end
+  end
+
+  def update_profile(%{assigns: %{user: user}} = conn, params) do
+    params = add_profile_emoji(user, params)
+    info_cng = build_info_cng(user, params)
 
     with changeset <- User.update_changeset(user, params),
+         changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng),
          {:ok, user} <- User.update_and_set_cache(changeset) do
       CommonAPI.update(user)
       render(conn, UserView, "user.json", %{user: user, for: user})
@@ -503,6 +500,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     |> render(ActivityView, "index.json", %{activities: activities, for: user})
   end
 
+  def search_user(%{assigns: %{user: user}} = conn, %{"query" => query}) do
+    users = User.search(query, true)
+
+    conn
+    |> render(UserView, "index.json", %{users: users, for: user})
+  end
+
   defp bad_request_reply(conn, error_message) do
     json = error_json(conn, error_message)
     json_reply(conn, 400, json)