Add OpenAPI spec for PleromaAPI.ScrobbleController
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 19 May 2020 11:53:18 +0000 (15:53 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Tue, 19 May 2020 12:26:06 +0000 (16:26 +0400)
lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex [new file with mode: 0644]
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
lib/pleroma/web/router.ex
test/web/common_api/common_api_test.exs
test/web/pleroma_api/controllers/scrobble_controller_test.exs

diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex
new file mode 100644 (file)
index 0000000..779b8f8
--- /dev/null
@@ -0,0 +1,102 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
+  alias OpenApiSpex.Operation
+  alias OpenApiSpex.Reference
+  alias OpenApiSpex.Schema
+  alias Pleroma.Web.ApiSpec.Schemas.Account
+  alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
+
+  import Pleroma.Web.ApiSpec.Helpers
+
+  def open_api_operation(action) do
+    operation = String.to_existing_atom("#{action}_operation")
+    apply(__MODULE__, operation, [])
+  end
+
+  def create_operation do
+    %Operation{
+      tags: ["Scrobbles"],
+      summary: "Gets user mascot image",
+      security: [%{"oAuth" => ["write"]}],
+      operationId: "PleromaAPI.ScrobbleController.create",
+      requestBody: request_body("Parameters", create_request(), requried: true),
+      responses: %{
+        200 => Operation.response("Scrobble", "application/json", scrobble())
+      }
+    }
+  end
+
+  def index_operation do
+    %Operation{
+      tags: ["Scrobbles"],
+      summary: "Requests a list of current and recent Listen activities for an account",
+      operationId: "PleromaAPI.ScrobbleController.index",
+      parameters: [
+        %Reference{"$ref": "#/components/parameters/accountIdOrNickname"} | pagination_params()
+      ],
+      security: [%{"oAuth" => ["read"]}],
+      responses: %{
+        200 =>
+          Operation.response("Array of Scrobble", "application/json", %Schema{
+            type: :array,
+            items: scrobble()
+          })
+      }
+    }
+  end
+
+  defp create_request do
+    %Schema{
+      type: :object,
+      required: [:title],
+      properties: %{
+        title: %Schema{type: :string, description: "The title of the media playing"},
+        album: %Schema{type: :string, description: "The album of the media playing"},
+        artist: %Schema{type: :string, description: "The artist of the media playing"},
+        length: %Schema{type: :integer, description: "The length of the media playing"},
+        visibility: %Schema{
+          allOf: [VisibilityScope],
+          default: "public",
+          description: "Scrobble visibility"
+        }
+      },
+      example: %{
+        "title" => "Some Title",
+        "artist" => "Some Artist",
+        "album" => "Some Album",
+        "length" => 180_000
+      }
+    }
+  end
+
+  defp scrobble do
+    %Schema{
+      type: :object,
+      properties: %{
+        id: %Schema{type: :string},
+        account: Account,
+        title: %Schema{type: :string, description: "The title of the media playing"},
+        album: %Schema{type: :string, description: "The album of the media playing"},
+        artist: %Schema{type: :string, description: "The artist of the media playing"},
+        length: %Schema{
+          type: :integer,
+          description: "The length of the media playing",
+          nullable: true
+        },
+        created_at: %Schema{type: :string, format: :"date-time"}
+      },
+      example: %{
+        "id" => "1234",
+        "account" => Account.schema().example,
+        "title" => "Some Title",
+        "artist" => "Some Artist",
+        "album" => "Some Album",
+        "length" => 180_000,
+        "created_at" => "2019-09-28T12:40:45.000Z"
+      }
+    }
+  end
+end
index 7c94f16b61b5110139370a505a610db404847698..447dbe4e68791a0be6d04a457ec6aa457c5ed1d7 100644 (file)
@@ -347,11 +347,14 @@ defmodule Pleroma.Web.CommonAPI do
     |> check_expiry_date()
   end
 
-  def listen(user, %{"title" => _} = data) do
-    with visibility <- data["visibility"] || "public",
-         {to, cc} <- get_to_and_cc(user, [], nil, visibility, nil),
+  def listen(user, data) do
+    visibility = Map.get(data, :visibility, "public")
+
+    with {to, cc} <- get_to_and_cc(user, [], nil, visibility, nil),
          listen_data <-
-           Map.take(data, ["album", "artist", "title", "length"])
+           data
+           |> Map.take([:album, :artist, :title, :length])
+           |> Map.new(fn {key, value} -> {to_string(key), value} end)
            |> Map.put("type", "Audio")
            |> Map.put("to", to)
            |> Map.put("cc", cc)
index 22da6c0ad6cf820a691e052635ac1a74059d95bb..35a37f69e2b799613220bddec9b97d2631f52b12 100644 (file)
@@ -5,7 +5,7 @@
 defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
   use Pleroma.Web, :controller
 
-  import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, fetch_integer_param: 2]
+  import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
 
   alias Pleroma.Plugs.OAuthScopesPlug
   alias Pleroma.User
@@ -13,22 +13,18 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
   alias Pleroma.Web.CommonAPI
   alias Pleroma.Web.MastodonAPI.StatusView
 
+  plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :user_scrobbles
+    %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :index
   )
 
-  plug(OAuthScopesPlug, %{scopes: ["write"]} when action != :user_scrobbles)
+  plug(OAuthScopesPlug, %{scopes: ["write"]} when action == :create)
 
-  def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do
-    params =
-      if !params["length"] do
-        params
-      else
-        params
-        |> Map.put("length", fetch_integer_param(params, "length"))
-      end
+  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaScrobbleOperation
 
+  def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
     with {:ok, activity} <- CommonAPI.listen(user, params) do
       conn
       |> put_view(StatusView)
@@ -41,9 +37,12 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
     end
   end
 
-  def user_scrobbles(%{assigns: %{user: reading_user}} = conn, params) do
-    with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do
-      params = Map.put(params, "type", ["Listen"])
+  def index(%{assigns: %{user: reading_user}} = conn, %{id: id} = params) do
+    with %User{} = user <- User.get_cached_by_nickname_or_id(id, for: reading_user) do
+      params =
+        params
+        |> Map.new(fn {key, value} -> {to_string(key), value} end)
+        |> Map.put("type", ["Listen"])
 
       activities = ActivityPub.fetch_user_abstract_activities(user, reading_user, params)
 
index d77a61361285c6e5f992b91298dcb58fe471f6b0..369c54cf4de91a557cf6384c3d12c7f640d906df 100644 (file)
@@ -325,7 +325,7 @@ defmodule Pleroma.Web.Router do
       get("/mascot", MascotController, :show)
       put("/mascot", MascotController, :update)
 
-      post("/scrobble", ScrobbleController, :new_scrobble)
+      post("/scrobble", ScrobbleController, :create)
     end
 
     scope [] do
@@ -345,7 +345,7 @@ defmodule Pleroma.Web.Router do
 
   scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
     pipe_through(:api)
-    get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles)
+    get("/accounts/:id/scrobbles", ScrobbleController, :index)
   end
 
   scope "/api/v1", Pleroma.Web.MastodonAPI do
index fd829901350e17eae2840dd12ee84456403bda48..52e95397cf005107aa613c93069d97b7a686b38b 100644 (file)
@@ -841,10 +841,10 @@ defmodule Pleroma.Web.CommonAPITest do
 
       {:ok, activity} =
         CommonAPI.listen(user, %{
-          "title" => "lain radio episode 1",
-          "album" => "lain radio",
-          "artist" => "lain",
-          "length" => 180_000
+          title: "lain radio episode 1",
+          album: "lain radio",
+          artist: "lain",
+          length: 180_000
         })
 
       object = Object.normalize(activity)
@@ -859,11 +859,11 @@ defmodule Pleroma.Web.CommonAPITest do
 
       {:ok, activity} =
         CommonAPI.listen(user, %{
-          "title" => "lain radio episode 1",
-          "album" => "lain radio",
-          "artist" => "lain",
-          "length" => 180_000,
-          "visibility" => "private"
+          title: "lain radio episode 1",
+          album: "lain radio",
+          artist: "lain",
+          length: 180_000,
+          visibility: "private"
         })
 
       object = Object.normalize(activity)
index 1b945040c2c0e75a080f47e784c36153e3d9a6c3..f39c07ac649ea52986a477c3c728dcd13680a33e 100644 (file)
@@ -12,14 +12,16 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
       %{conn: conn} = oauth_access(["write"])
 
       conn =
-        post(conn, "/api/v1/pleroma/scrobble", %{
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/pleroma/scrobble", %{
           "title" => "lain radio episode 1",
           "artist" => "lain",
           "album" => "lain radio",
           "length" => "180000"
         })
 
-      assert %{"title" => "lain radio episode 1"} = json_response(conn, 200)
+      assert %{"title" => "lain radio episode 1"} = json_response_and_validate_schema(conn, 200)
     end
   end
 
@@ -29,28 +31,28 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
 
       {:ok, _activity} =
         CommonAPI.listen(user, %{
-          "title" => "lain radio episode 1",
-          "artist" => "lain",
-          "album" => "lain radio"
+          title: "lain radio episode 1",
+          artist: "lain",
+          album: "lain radio"
         })
 
       {:ok, _activity} =
         CommonAPI.listen(user, %{
-          "title" => "lain radio episode 2",
-          "artist" => "lain",
-          "album" => "lain radio"
+          title: "lain radio episode 2",
+          artist: "lain",
+          album: "lain radio"
         })
 
       {:ok, _activity} =
         CommonAPI.listen(user, %{
-          "title" => "lain radio episode 3",
-          "artist" => "lain",
-          "album" => "lain radio"
+          title: "lain radio episode 3",
+          artist: "lain",
+          album: "lain radio"
         })
 
       conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles")
 
-      result = json_response(conn, 200)
+      result = json_response_and_validate_schema(conn, 200)
 
       assert length(result) == 3
     end