Add API endpoints for a custom user mascot
authorSadposter <hannah+pleroma@coffee-and-dreams.uk>
Mon, 20 May 2019 11:39:23 +0000 (12:39 +0100)
committerSadposter <hannah+pleroma@coffee-and-dreams.uk>
Mon, 20 May 2019 11:39:23 +0000 (12:39 +0100)
docs/api/pleroma_api.md
lib/pleroma/user/info.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/router.ex

index dd0b6ca733dc79e47ccc75c4ef9aa7c4956d7ebc..4d99a2d2bfdaad8976fc763561df976ec1d428f8 100644 (file)
@@ -252,6 +252,45 @@ See [Admin-API](Admin-API.md)
 ]
 ```
 
+## `/api/v1/pleroma/mascot`
+### Gets user mascot image
+* Method `GET`
+* Authentication: required
+
+* Response: JSON. Returns a mastodon media attachment entity.
+* Example response:
+```json
+{
+    "id": "abcdefg",
+    "url": "https://pleroma.example.org/media/abcdefg.png",
+    "type": "image",
+    "pleroma": {
+        "mime_type": "image/png"
+    }
+}
+```
+
+### Updates user mascot image
+* Method `PUT`
+* Authentication: required
+* Params:
+    * `image`: Multipart image
+* Response: JSON. Returns a mastodon media attachment entity
+  when successful, otherwise returns HTTP 415 `{"error": "error_msg"}`
+* Example response:
+```json
+{
+    "id": "abcdefg",
+    "url": "https://pleroma.example.org/media/abcdefg.png",
+    "type": "image",
+    "pleroma": {
+        "mime_type": "image/png"
+    }
+}
+```
+* Note: Behaves exactly the same as `POST /api/v1/upload`.
+  Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.
+
 ## `/api/pleroma/notification_settings`
 ### Updates user notification settings
 * Method `PUT`
index 5f0cefc00ddb2f4610c9c1f92b5bb87e52e510f9..ffcd06e3ebcc1037538eca73edcdea5fe2689cb6 100644 (file)
@@ -43,6 +43,19 @@ defmodule Pleroma.User.Info do
     field(:hide_favorites, :boolean, default: true)
     field(:pinned_activities, {:array, :string}, default: [])
     field(:flavour, :string, default: nil)
+
+    field(:mascot, :map,
+      default: %{
+        id: "pleromatan",
+        url: "/images/pleroma-fox-tan-smol.png",
+        type: "image",
+        preview_url: "/images/pleroma-fox-tan-smol.png",
+        pleroma: %{
+          mime_type: "image/png"
+        }
+      }
+    )
+
     field(:emoji, {:array, :map}, default: [])
 
     field(:notification_settings, :map,
@@ -248,6 +261,14 @@ defmodule Pleroma.User.Info do
     |> validate_required([:flavour])
   end
 
+  def mascot_update(info, url) do
+    params = %{mascot: url}
+
+    info
+    |> cast(params, [:mascot])
+    |> validate_required([:mascot])
+  end
+
   def set_source_data(info, source_data) do
     params = %{source_data: source_data}
 
index 1051861ff9a9e3992065e264bbc4f270a1dedc8c..67f3638594479ebcfab994dcc0c2960c6653caa1 100644 (file)
@@ -707,6 +707,40 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     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),
+         %{type: type} = rendered <-
+           StatusView.render("attachment.json", %{attachment: attachment_data}) do
+      # Reject if not an image
+      if type == "image" do
+        # Sure!
+        # Save to the user's info
+        info_changeset = User.Info.mascot_update(user.info, rendered)
+
+        user_changeset =
+          user
+          |> Ecto.Changeset.change()
+          |> Ecto.Changeset.put_embed(:info, info_changeset)
+
+        {:ok, _user} = User.update_and_set_cache(user_changeset)
+
+        conn
+        |> json(rendered)
+      else
+        conn
+        |> send_resp(415, Jason.encode!(%{"error" => "mascots can only be images"}))
+      end
+    end
+  end
+
+  def get_mascot(%{assigns: %{user: user}} = conn, _params) do
+    %{info: %{mascot: mascot}} = user
+
+    conn
+    |> json(mascot)
+  end
+
   def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
     with %Activity{data: %{"object" => object}} <- Repo.get(Activity, id),
          %Object{data: %{"likes" => likes}} <- Object.normalize(object) do
@@ -1329,7 +1363,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
             display_sensitive_media: false,
             reduce_motion: false,
             max_toot_chars: limit,
-            mascot: "/images/pleroma-fox-tan-smol.png"
+            mascot: Map.get(user.info.mascot, "url", "/images/pleroma-fox-tan-smol.png")
           },
           rights: %{
             delete_others_notice: present?(user.info.is_moderator),
index 6a4e4a1d4e77d098d701352833ccdfc0686ba42d..4c29b24eb47d465bc838c575e42566ab3f8e5632 100644 (file)
@@ -352,6 +352,9 @@ defmodule Pleroma.Web.Router do
 
       post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
 
+      get("/pleroma/mascot", MastodonAPIController, :get_mascot)
+      put("/pleroma/mascot", MastodonAPIController, :set_mascot)
+
       post("/reports", MastodonAPIController, :reports)
     end