Add OpenAPI spec for PleromaAPI.ScrobbleController

This commit is contained in:
Egor Kislitsyn 2020-05-19 15:53:18 +04:00
parent 7075fa92a5
commit 524d04d921
No known key found for this signature in database
GPG key ID: 1B49CB15B71E7805
6 changed files with 147 additions and 41 deletions

View file

@ -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

View file

@ -347,11 +347,14 @@ def check_expiry_date(expiry_str) do
|> check_expiry_date() |> check_expiry_date()
end end
def listen(user, %{"title" => _} = data) do def listen(user, data) do
with visibility <- data["visibility"] || "public", visibility = Map.get(data, :visibility, "public")
{to, cc} <- get_to_and_cc(user, [], nil, visibility, nil),
with {to, cc} <- get_to_and_cc(user, [], nil, visibility, nil),
listen_data <- 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("type", "Audio")
|> Map.put("to", to) |> Map.put("to", to)
|> Map.put("cc", cc) |> Map.put("cc", cc)

View file

@ -5,7 +5,7 @@
defmodule Pleroma.Web.PleromaAPI.ScrobbleController do defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
use Pleroma.Web, :controller 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.Plugs.OAuthScopesPlug
alias Pleroma.User alias Pleroma.User
@ -13,22 +13,18 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug( plug(
OAuthScopesPlug, 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 defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaScrobbleOperation
params =
if !params["length"] do
params
else
params
|> Map.put("length", fetch_integer_param(params, "length"))
end
def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
with {:ok, activity} <- CommonAPI.listen(user, params) do with {:ok, activity} <- CommonAPI.listen(user, params) do
conn conn
|> put_view(StatusView) |> put_view(StatusView)
@ -41,9 +37,12 @@ def new_scrobble(%{assigns: %{user: user}} = conn, %{"title" => _} = params) do
end end
end end
def user_scrobbles(%{assigns: %{user: reading_user}} = conn, params) do def index(%{assigns: %{user: reading_user}} = conn, %{id: id} = params) do
with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do with %User{} = user <- User.get_cached_by_nickname_or_id(id, for: reading_user) do
params = Map.put(params, "type", ["Listen"]) 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) activities = ActivityPub.fetch_user_abstract_activities(user, reading_user, params)

View file

@ -325,7 +325,7 @@ defmodule Pleroma.Web.Router do
get("/mascot", MascotController, :show) get("/mascot", MascotController, :show)
put("/mascot", MascotController, :update) put("/mascot", MascotController, :update)
post("/scrobble", ScrobbleController, :new_scrobble) post("/scrobble", ScrobbleController, :create)
end end
scope [] do scope [] do
@ -345,7 +345,7 @@ defmodule Pleroma.Web.Router do
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
pipe_through(:api) pipe_through(:api)
get("/accounts/:id/scrobbles", ScrobbleController, :user_scrobbles) get("/accounts/:id/scrobbles", ScrobbleController, :index)
end end
scope "/api/v1", Pleroma.Web.MastodonAPI do scope "/api/v1", Pleroma.Web.MastodonAPI do

View file

@ -841,10 +841,10 @@ test "returns a valid activity" do
{:ok, activity} = {:ok, activity} =
CommonAPI.listen(user, %{ CommonAPI.listen(user, %{
"title" => "lain radio episode 1", title: "lain radio episode 1",
"album" => "lain radio", album: "lain radio",
"artist" => "lain", artist: "lain",
"length" => 180_000 length: 180_000
}) })
object = Object.normalize(activity) object = Object.normalize(activity)
@ -859,11 +859,11 @@ test "respects visibility=private" do
{:ok, activity} = {:ok, activity} =
CommonAPI.listen(user, %{ CommonAPI.listen(user, %{
"title" => "lain radio episode 1", title: "lain radio episode 1",
"album" => "lain radio", album: "lain radio",
"artist" => "lain", artist: "lain",
"length" => 180_000, length: 180_000,
"visibility" => "private" visibility: "private"
}) })
object = Object.normalize(activity) object = Object.normalize(activity)

View file

@ -12,14 +12,16 @@ test "works correctly" do
%{conn: conn} = oauth_access(["write"]) %{conn: conn} = oauth_access(["write"])
conn = 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", "title" => "lain radio episode 1",
"artist" => "lain", "artist" => "lain",
"album" => "lain radio", "album" => "lain radio",
"length" => "180000" "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
end end
@ -29,28 +31,28 @@ test "works correctly" do
{:ok, _activity} = {:ok, _activity} =
CommonAPI.listen(user, %{ CommonAPI.listen(user, %{
"title" => "lain radio episode 1", title: "lain radio episode 1",
"artist" => "lain", artist: "lain",
"album" => "lain radio" album: "lain radio"
}) })
{:ok, _activity} = {:ok, _activity} =
CommonAPI.listen(user, %{ CommonAPI.listen(user, %{
"title" => "lain radio episode 2", title: "lain radio episode 2",
"artist" => "lain", artist: "lain",
"album" => "lain radio" album: "lain radio"
}) })
{:ok, _activity} = {:ok, _activity} =
CommonAPI.listen(user, %{ CommonAPI.listen(user, %{
"title" => "lain radio episode 3", title: "lain radio episode 3",
"artist" => "lain", artist: "lain",
"album" => "lain radio" album: "lain radio"
}) })
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles") 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 assert length(result) == 3
end end