From cf0ad02ea961ae8cb6cc4f960afaeead58ecd4af Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Tue, 19 Jul 2022 15:07:45 +0100 Subject: [PATCH] Remove scrobbling support --- lib/pleroma/web/activity_pub/activity_pub.ex | 20 ---- .../web/activity_pub/transmogrifier.ex | 33 +----- lib/pleroma/web/activity_pub/utils.ex | 15 --- .../web/activity_pub/views/object_view.ex | 2 +- lib/pleroma/web/api_spec.ex | 2 +- .../operations/pleroma_scrobble_operation.ex | 102 ------------------ lib/pleroma/web/common_api.ex | 6 -- lib/pleroma/web/common_api/activity_draft.ex | 24 ----- .../controllers/scrobble_controller.ex | 52 --------- .../web/pleroma_api/views/scrobble_view.ex | 37 ------- lib/pleroma/web/router.ex | 3 - .../web/activity_pub/activity_pub_test.exs | 36 ------- .../transmogrifier/audio_handling_test.exs | 33 ------ .../web/activity_pub/transmogrifier_test.exs | 14 --- test/pleroma/web/common_api_test.exs | 39 ------- .../controllers/scrobble_controller_test.exs | 60 ----------- .../pleroma_api/views/scrobble_view_test.exs | 20 ---- 17 files changed, 3 insertions(+), 495 deletions(-) delete mode 100644 lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex delete mode 100644 lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex delete mode 100644 lib/pleroma/web/pleroma_api/views/scrobble_view.ex delete mode 100644 test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs delete mode 100644 test/pleroma/web/pleroma_api/views/scrobble_view_test.exs diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 236181b07..3583f1626 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -318,26 +318,6 @@ defp maybe_schedule_poll_notifications(activity) do :ok end - @spec listen(map()) :: {:ok, Activity.t()} | {:error, any()} - def listen(%{to: to, actor: actor, context: context, object: object} = params) do - additional = params[:additional] || %{} - # only accept false as false value - local = !(params[:local] == false) - published = params[:published] - - listen_data = - make_listen_data( - %{to: to, actor: actor, published: published, context: context, object: object}, - additional - ) - - with {:ok, activity} <- insert(listen_data, local), - _ <- notify_and_stream(activity), - :ok <- maybe_federate(activity) do - {:ok, activity} - end - end - @spec unfollow(User.t(), User.t(), String.t() | nil, boolean()) :: {:ok, Activity.t()} | nil | {:error, any()} def unfollow(follower, followed, activity_id \\ nil, local \\ true) do diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index cf0c9a9e2..cf072f7ac 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -384,37 +384,6 @@ def handle_incoming(%{"id" => ""}, _options), do: :error def handle_incoming(%{"id" => id}, _options) when is_binary(id) and byte_size(id) < 8, do: :error - def handle_incoming( - %{"type" => "Listen", "object" => %{"type" => "Audio"} = object} = data, - options - ) do - actor = Containment.get_actor(data) - - data = - Map.put(data, "actor", actor) - |> fix_addressing - - with {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(data["actor"]) do - reply_depth = (options[:depth] || 0) + 1 - options = Keyword.put(options, :depth, reply_depth) - object = fix_object(object, options) - - params = %{ - to: data["to"], - object: object, - actor: user, - context: nil, - local: false, - published: data["published"], - additional: Map.take(data, ["cc", "id"]) - } - - ActivityPub.listen(params) - else - _e -> :error - end - end - @doc "Rewrite misskey likes into EmojiReacts" def handle_incoming( %{ @@ -695,7 +664,7 @@ def prepare_object(object) do # """ def prepare_outgoing(%{"type" => activity_type, "object" => object_id} = data) - when activity_type in ["Create", "Listen"] do + when activity_type in ["Create"] do object = object_id |> Object.normalize(fetch: false) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6a8360def..0e92deb31 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -713,21 +713,6 @@ def make_create_data(params, additional) do |> Map.merge(additional) end - #### Listen-related helpers - def make_listen_data(params, additional) do - published = params.published || make_date() - - %{ - "type" => "Listen", - "to" => params.to |> Enum.uniq(), - "actor" => params.actor.ap_id, - "object" => params.object, - "published" => published, - "context" => params.context - } - |> Map.merge(additional) - end - #### Flag-related helpers @spec make_flag_data(map(), map()) :: map() def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex index 8a3e4d77b..d9b59406c 100644 --- a/lib/pleroma/web/activity_pub/views/object_view.ex +++ b/lib/pleroma/web/activity_pub/views/object_view.ex @@ -16,7 +16,7 @@ def render("object.json", %{object: %Object{} = object}) do end def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity}) - when activity_type in ["Create", "Listen"] do + when activity_type in ["Create"] do base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header() object = Object.normalize(activity, fetch: false) diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex index 528cd9cf4..66ae7dcf8 100644 --- a/lib/pleroma/web/api_spec.ex +++ b/lib/pleroma/web/api_spec.ex @@ -79,7 +79,7 @@ def spec(opts \\ []) do "x-tagGroups": [ %{ "name" => "Accounts", - "tags" => ["Account actions", "Retrieve account information", "Scrobbles"] + "tags" => ["Account actions", "Retrieve account information"] }, %{ "name" => "Administration", diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex deleted file mode 100644 index 6a909fc85..000000000 --- a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex +++ /dev/null @@ -1,102 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# 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: "Creates a new Listen activity for an account", - 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 diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index 856fa95b9..3c2e7ae86 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -388,12 +388,6 @@ def check_expiry_date(expiry_str) do |> check_expiry_date() end - def listen(user, data) do - with {:ok, draft} <- ActivityDraft.listen(user, data) do - ActivityPub.listen(draft.changes) - end - end - def post(user, %{status: _} = data) do with {:ok, draft} <- ActivityDraft.create(user, data) do ActivityPub.create(draft.changes, draft.preview?) diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex index bd56b6e20..ea88213fb 100644 --- a/lib/pleroma/web/common_api/activity_draft.ex +++ b/lib/pleroma/web/common_api/activity_draft.ex @@ -64,30 +64,6 @@ def create(user, params) do |> validate() end - def listen(user, params) do - user - |> new(params) - |> visibility() - |> to_and_cc() - |> context() - |> listen_object() - |> with_valid(&changes/1) - |> validate() - end - - defp listen_object(draft) do - object = - draft.params - |> Map.take([:album, :artist, :title, :length]) - |> Map.new(fn {key, value} -> {to_string(key), value} end) - |> Map.put("type", "Audio") - |> Map.put("to", draft.to) - |> Map.put("cc", draft.cc) - |> Map.put("actor", draft.user.ap_id) - - %__MODULE__{draft | object: object} - end - defp put_params(draft, params) do params = Map.put_new(params, :in_reply_to_status_id, params[:in_reply_to_id]) %__MODULE__{draft | params: params} diff --git a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex deleted file mode 100644 index ca26d80ef..000000000 --- a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex +++ /dev/null @@ -1,52 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.ScrobbleController do - use Pleroma.Web, :controller - - import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] - - alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.CommonAPI - alias Pleroma.Web.Plugs.OAuthScopesPlug - - plug(Pleroma.Web.ApiSpec.CastAndValidate) - - plug( - OAuthScopesPlug, - %{scopes: ["read"], fallback: :proceed_unauthenticated} when action == :index - ) - - plug(OAuthScopesPlug, %{scopes: ["write"]} when action == :create) - - 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 - render(conn, "show.json", activity: activity, for: user) - else - {:error, message} -> - conn - |> put_status(:bad_request) - |> json(%{"error" => message}) - end - end - - 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 = Map.put(params, :type, ["Listen"]) - - activities = ActivityPub.fetch_user_abstract_activities(user, reading_user, params) - - conn - |> add_link_headers(activities) - |> render("index.json", %{ - activities: activities, - for: reading_user, - as: :activity - }) - end - end -end diff --git a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex deleted file mode 100644 index 2bc069529..000000000 --- a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex +++ /dev/null @@ -1,37 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.ScrobbleView do - use Pleroma.Web, :view - - require Pleroma.Constants - - alias Pleroma.Activity - alias Pleroma.HTML - alias Pleroma.Object - alias Pleroma.Web.CommonAPI - alias Pleroma.Web.CommonAPI.Utils - alias Pleroma.Web.MastodonAPI.AccountView - - def render("show.json", %{activity: %Activity{data: %{"type" => "Listen"}} = activity} = opts) do - object = Object.normalize(activity, fetch: false) - - user = CommonAPI.get_user(activity.data["actor"]) - created_at = Utils.to_masto_date(activity.data["published"]) - - %{ - id: activity.id, - account: AccountView.render("show.json", %{user: user, for: opts[:for]}), - created_at: created_at, - title: object.data["title"] |> HTML.strip_tags(), - artist: object.data["artist"] |> HTML.strip_tags(), - album: object.data["album"] |> HTML.strip_tags(), - length: object.data["length"] - } - end - - def render("index.json", opts) do - safe_render_many(opts.activities, __MODULE__, "show.json", opts) - end -end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index f53a73895..9974e3dee 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -448,8 +448,6 @@ defmodule Pleroma.Web.Router do get("/mascot", MascotController, :show) put("/mascot", MascotController, :update) - post("/scrobble", ScrobbleController, :create) - get("/backups", BackupController, :index) post("/backups", BackupController, :create) end @@ -471,7 +469,6 @@ defmodule Pleroma.Web.Router do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do pipe_through(:api) - get("/accounts/:id/scrobbles", ScrobbleController, :index) get("/federation_status", InstancesController, :show) end diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index f85c4bbb8..964437906 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -543,42 +543,6 @@ test "adds an id to a given object if it lacks one and is a note and inserts it end end - describe "listen activities" do - test "does not increase user note count" do - user = insert(:user) - - {:ok, activity} = - ActivityPub.listen(%{ - to: ["https://www.w3.org/ns/activitystreams#Public"], - actor: user, - context: "", - object: %{ - "actor" => user.ap_id, - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "artist" => "lain", - "title" => "lain radio episode 1", - "length" => 180_000, - "type" => "Audio" - } - }) - - assert activity.actor == user.ap_id - - user = User.get_cached_by_id(user.id) - assert user.note_count == 0 - end - - test "can be fetched into a timeline" do - _listen_activity_1 = insert(:listen) - _listen_activity_2 = insert(:listen) - _listen_activity_3 = insert(:listen) - - timeline = ActivityPub.fetch_activities([], %{type: ["Listen"]}) - - assert length(timeline) == 3 - end - end - describe "create activities" do setup do [user: insert(:user)] diff --git a/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs index a0942ce8b..0a1a965ca 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -12,39 +12,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do import Pleroma.Factory - test "it works for incoming listens" do - _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin") - - data = %{ - "@context" => "https://www.w3.org/ns/activitystreams", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "type" => "Listen", - "id" => "http://mastodon.example.org/users/admin/listens/1234/activity", - "actor" => "http://mastodon.example.org/users/admin", - "object" => %{ - "type" => "Audio", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "id" => "http://mastodon.example.org/users/admin/listens/1234", - "attributedTo" => "http://mastodon.example.org/users/admin", - "title" => "lain radio episode 1", - "artist" => "lain", - "album" => "lain radio", - "length" => 180_000 - } - } - - {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - - object = Object.normalize(activity, fetch: false) - - assert object.data["title"] == "lain radio episode 1" - assert object.data["artist"] == "lain" - assert object.data["album"] == "lain radio" - assert object.data["length"] == 180_000 - end - test "Funkwhale Audio object" do Tesla.Mock.mock(fn %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} -> diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 06daf6a9f..3756fdee0 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -273,20 +273,6 @@ test "it strips BCC field" do assert is_nil(modified["bcc"]) end - test "it can handle Listen activities" do - listen_activity = insert(:listen) - - {:ok, modified} = Transmogrifier.prepare_outgoing(listen_activity.data) - - assert modified["type"] == "Listen" - - user = insert(:user) - - {:ok, activity} = CommonAPI.listen(user, %{"title" => "lain radio episode 1"}) - - {:ok, _modified} = Transmogrifier.prepare_outgoing(activity.data) - end - test "custom emoji urls are URI encoded" do # :dinosaur: filename has a space -> dino walking.gif user = insert(:user) diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 85a4a3a11..167909cfb 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -1331,45 +1331,6 @@ test "does not allow to vote twice" do end end - describe "listen/2" do - test "returns a valid activity" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.listen(user, %{ - title: "lain radio episode 1", - album: "lain radio", - artist: "lain", - length: 180_000 - }) - - object = Object.normalize(activity, fetch: false) - - assert object.data["title"] == "lain radio episode 1" - - assert Visibility.get_visibility(activity) == "public" - end - - test "respects visibility=private" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.listen(user, %{ - title: "lain radio episode 1", - album: "lain radio", - artist: "lain", - length: 180_000, - visibility: "private" - }) - - object = Object.normalize(activity, fetch: false) - - assert object.data["title"] == "lain radio episode 1" - - assert Visibility.get_visibility(activity) == "private" - end - end - describe "get_user/1" do test "gets user by ap_id" do user = insert(:user) diff --git a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs deleted file mode 100644 index d4546f442..000000000 --- a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs +++ /dev/null @@ -1,60 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do - use Pleroma.Web.ConnCase, async: true - - alias Pleroma.Web.CommonAPI - - describe "POST /api/v1/pleroma/scrobble" do - test "works correctly" do - %{conn: conn} = oauth_access(["write"]) - - conn = - 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_and_validate_schema(conn, 200) - end - end - - describe "GET /api/v1/pleroma/accounts/:id/scrobbles" do - test "works correctly" do - %{user: user, conn: conn} = oauth_access(["read"]) - - {:ok, _activity} = - CommonAPI.listen(user, %{ - 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" - }) - - {:ok, _activity} = - CommonAPI.listen(user, %{ - title: "lain radio episode 3", - artist: "lain", - album: "lain radio" - }) - - conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles") - - result = json_response_and_validate_schema(conn, 200) - - assert length(result) == 3 - end - end -end diff --git a/test/pleroma/web/pleroma_api/views/scrobble_view_test.exs b/test/pleroma/web/pleroma_api/views/scrobble_view_test.exs deleted file mode 100644 index 382051f6f..000000000 --- a/test/pleroma/web/pleroma_api/views/scrobble_view_test.exs +++ /dev/null @@ -1,20 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.ScrobbleViewTest do - use Pleroma.DataCase, async: true - - alias Pleroma.Web.PleromaAPI.ScrobbleView - - import Pleroma.Factory - - test "successfully renders a Listen activity (pleroma extension)" do - listen_activity = insert(:listen) - - status = ScrobbleView.render("show.json", activity: listen_activity) - - assert status.length == listen_activity.data["object"]["length"] - assert status.title == listen_activity.data["object"]["title"] - end -end