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