diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/user/info.ex | 23 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 34 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 29 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 2 |
5 files changed, 89 insertions, 7 deletions
diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 2f419a5a2..ffb800177 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -31,6 +31,7 @@ defmodule Pleroma.User.Info do field(:hub, :string, default: nil) field(:salmon, :string, default: nil) field(:hide_network, :boolean, default: false) + field(:pinned_activities, {:array, :integer}, default: []) # Found in the wild # ap_id -> Where is this used? @@ -198,4 +199,26 @@ defmodule Pleroma.User.Info do :is_admin ]) end + + def add_pinnned_activity(info, %Pleroma.Activity{id: id}) do + if id not in info.pinned_activities do + max_pinned_posts = Pleroma.Config.get([:instance, :max_pinned_posts], 0) + params = %{pinned_activities: info.pinned_activities ++ [id]} + + info + |> cast(params, [:pinned_activities]) + |> validate_length(:pinned_activities, + max: max_pinned_posts, + message: "You have already pinned the maximum number of toots" + ) + else + change(info) + end + end + + def remove_pinnned_activity(info, %Pleroma.Activity{id: id}) do + params = %{pinned_activities: List.delete(info.pinned_activities, id)} + + cast(info, params, [:pinned_activities]) + end end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4685f6d95..c5f62c4f8 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -394,6 +394,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Map.put("type", ["Create", "Announce"]) |> Map.put("actor_id", user.ap_id) |> Map.put("whole_db", true) + |> Map.put("pinned_activity_ids", user.info.pinned_activities) recipients = if reading_user do @@ -552,6 +553,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do ) end + defp restrict_pinned(query, %{"pinned" => "true", "pinned_activity_ids" => ids}) do + from(activity in query, where: activity.id in ^ids) + end + + defp restrict_pinned(query, _), do: query + def fetch_activities_query(recipients, opts \\ %{}) do base_query = from( @@ -576,6 +583,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_visibility(opts) |> restrict_replies(opts) |> restrict_reblogs(opts) + |> restrict_pinned(opts) end def fetch_activities(recipients, opts \\ %{}) do diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index bb3c38f00..6d22813b2 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -164,4 +164,38 @@ defmodule Pleroma.Web.CommonAPI do object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user}) }) end + + def pin(id_or_ap_id, user) do + with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), + %{valid?: true} = info_changeset <- + Pleroma.User.Info.add_pinnned_activity(user.info, activity), + changeset <- + Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset), + {:ok, _user} <- User.update_and_set_cache(changeset) do + {:ok, activity} + else + %{errors: [pinned_activities: {err, _}]} -> + {:error, err} + + _ -> + {:error, "Could not pin"} + end + end + + def unpin(id_or_ap_id, user) do + with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), + %{valid?: true} = info_changeset <- + Pleroma.User.Info.remove_pinnned_activity(user.info, activity), + changeset <- + Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset), + {:ok, _user} <- User.update_and_set_cache(changeset) do + {:ok, activity} + else + %{errors: [pinned_activities: {err, _}]} -> + {:error, err} + + _ -> + {:error, "Could not unpin"} + end + end end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 95d0f849c..2fb2943f1 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -256,13 +256,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do with %User{} = user <- Repo.get(User, params["id"]) do - # Since Pleroma has no "pinned" posts feature, we'll just set an empty list here - activities = - if params["pinned"] == "true" do - [] - else - ActivityPub.fetch_user_activities(user, reading_user, params) - end + activities = ActivityPub.fetch_user_activities(user, reading_user, params) conn |> add_link_headers(:user_statuses, activities, params["id"]) @@ -409,6 +403,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + def pin_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do + with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) + else + {:error, reason} -> + conn + |> put_resp_content_type("application/json") + |> send_resp(:bad_request, Jason.encode!(%{"error" => reason})) + end + end + + def unpin_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do + with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do + conn + |> put_view(StatusView) + |> try_render("status.json", %{activity: activity, for: user, as: :activity}) + end + end + def notifications(%{assigns: %{user: user}} = conn, params) do notifications = Notification.for_user(user, params) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 8df45bf4d..ad73d8867 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -188,6 +188,8 @@ defmodule Pleroma.Web.Router do post("/statuses/:id/unreblog", MastodonAPIController, :unreblog_status) post("/statuses/:id/favourite", MastodonAPIController, :fav_status) post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status) + post("/statuses/:id/pin", MastodonAPIController, :pin_status) + post("/statuses/:id/unpin", MastodonAPIController, :unpin_status) post("/notifications/clear", MastodonAPIController, :clear_notifications) post("/notifications/dismiss", MastodonAPIController, :dismiss_notification) |