MastoAPI: Profile directory
This commit is contained in:
parent
73609211a4
commit
de006443f0
16 changed files with 226 additions and 7 deletions
|
|
@ -149,6 +149,7 @@ defmodule Pleroma.User do
|
|||
field(:disclose_client, :boolean, default: true)
|
||||
field(:pinned_objects, :map, default: %{})
|
||||
field(:is_suggested, :boolean, default: false)
|
||||
field(:last_status_at, :naive_datetime)
|
||||
|
||||
embeds_one(
|
||||
:notification_settings,
|
||||
|
|
@ -2499,4 +2500,16 @@ defmodule Pleroma.User do
|
|||
|> where([u], u.local == true)
|
||||
|> Repo.aggregate(:count)
|
||||
end
|
||||
|
||||
def update_last_status_at(user) do
|
||||
User
|
||||
|> where(id: ^user.id)
|
||||
|> update([u], set: [last_status_at: fragment("NOW()")])
|
||||
|> select([u], u)
|
||||
|> Repo.update_all([])
|
||||
|> case do
|
||||
{1, [user]} -> set_cache(user)
|
||||
_ -> {:error, user}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ defmodule Pleroma.User.Query do
|
|||
is_admin: boolean(),
|
||||
is_moderator: boolean(),
|
||||
is_suggested: boolean(),
|
||||
is_discoverable: boolean(),
|
||||
super_users: boolean(),
|
||||
invisible: boolean(),
|
||||
internal: boolean(),
|
||||
|
|
@ -172,6 +173,10 @@ defmodule Pleroma.User.Query do
|
|||
where(query, [u], u.is_suggested == ^bool)
|
||||
end
|
||||
|
||||
defp compose_query({:is_discoverable, bool}, query) do
|
||||
where(query, [u], u.is_discoverable == ^bool)
|
||||
end
|
||||
|
||||
defp compose_query({:followers, %User{id: id}}, query) do
|
||||
query
|
||||
|> where([u], u.id != ^id)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
if is_public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}
|
||||
end
|
||||
|
||||
def update_last_status_at_if_public(actor, object) do
|
||||
if is_public?(object), do: User.update_last_status_at(actor), else: {:ok, actor}
|
||||
end
|
||||
|
||||
defp increase_replies_count_if_reply(%{
|
||||
"object" => %{"inReplyTo" => reply_ap_id} = object,
|
||||
"type" => "Create"
|
||||
|
|
@ -288,6 +292,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
_ <- increase_replies_count_if_reply(create_data),
|
||||
{:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity},
|
||||
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
|
||||
{:ok, _actor} <- update_last_status_at_if_public(actor, activity),
|
||||
_ <- notify_and_stream(activity),
|
||||
:ok <- maybe_schedule_poll_notifications(activity),
|
||||
:ok <- maybe_federate(activity) do
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||
{:ok, notifications} = Notification.create_notifications(activity, do_send: false)
|
||||
{:ok, _user} = ActivityPub.increase_note_count_if_public(user, object)
|
||||
{:ok, _user} = ActivityPub.update_last_status_at_if_public(user, object)
|
||||
|
||||
if in_reply_to = object.data["type"] != "Answer" && object.data["inReplyTo"] do
|
||||
Object.increase_replies_count(in_reply_to)
|
||||
|
|
|
|||
41
lib/pleroma/web/api_spec/operations/directory_operation.ex
Normal file
41
lib/pleroma/web/api_spec/operations/directory_operation.ex
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.DirectoryOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias Pleroma.Web.ApiSpec.AccountOperation
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def index_operation do
|
||||
%Operation{
|
||||
tags: ["Directory"],
|
||||
summary: "Profile directory",
|
||||
operationId: "DirectoryController.index",
|
||||
parameters:
|
||||
[
|
||||
Operation.parameter(
|
||||
:order,
|
||||
:query,
|
||||
:string,
|
||||
"Order by recent activity or account creation",
|
||||
required: nil
|
||||
),
|
||||
Operation.parameter(:local, :query, BooleanLike, "Include local users only")
|
||||
] ++ pagination_params(),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Accounts", "application/json", AccountOperation.array_of_accounts()),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.DirectoryController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Ecto.Query
|
||||
alias Pleroma.Pagination
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
|
||||
require Logger
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
|
||||
plug(:skip_auth when action == "index")
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DirectoryOperation
|
||||
|
||||
@doc "GET /api/v1/directory"
|
||||
def index(%{assigns: %{user: user}} = conn, params) do
|
||||
with true <- Pleroma.Config.get([:instance, :profile_directory]) do
|
||||
limit = Map.get(params, :limit, 20) |> min(80)
|
||||
|
||||
users =
|
||||
User.Query.build(%{is_discoverable: true, invisible: false, limit: limit})
|
||||
|> order_by_creation_date(params)
|
||||
|> exclude_remote(params)
|
||||
|> exclude_user(user)
|
||||
|> exclude_relationships(user, [:block, :mute])
|
||||
|> Pagination.fetch_paginated(params, :offset)
|
||||
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("index.json", for: user, users: users, as: :user)
|
||||
else
|
||||
_ -> json(conn, [])
|
||||
end
|
||||
end
|
||||
|
||||
defp order_by_creation_date(query, %{order: "new"}) do
|
||||
query
|
||||
end
|
||||
|
||||
defp order_by_creation_date(query, _params) do
|
||||
query
|
||||
|> order_by([u], desc_nulls_last: u.last_status_at)
|
||||
end
|
||||
|
||||
defp exclude_remote(query, %{local: true}) do
|
||||
where(query, [u], u.local == true)
|
||||
end
|
||||
|
||||
defp exclude_remote(query, _params) do
|
||||
query
|
||||
end
|
||||
|
||||
defp exclude_user(query, %User{id: user_id}) do
|
||||
where(query, [u], u.id != ^user_id)
|
||||
end
|
||||
|
||||
defp exclude_user(query, _user) do
|
||||
query
|
||||
end
|
||||
|
||||
defp exclude_relationships(query, %User{id: user_id}, relationship_types) do
|
||||
query
|
||||
|> join(:left, [u], r in UserRelationship,
|
||||
as: :user_relationships,
|
||||
on:
|
||||
r.target_id == u.id and r.source_id == ^user_id and
|
||||
r.relationship_type in ^relationship_types
|
||||
)
|
||||
|> where([user_relationships: r], is_nil(r.target_id))
|
||||
end
|
||||
|
||||
defp exclude_relationships(query, _user, _relationship_types) do
|
||||
query
|
||||
end
|
||||
end
|
||||
|
|
@ -270,6 +270,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
actor_type: user.actor_type
|
||||
}
|
||||
},
|
||||
last_status_at: user.last_status_at,
|
||||
|
||||
# Pleroma extensions
|
||||
# Note: it's insecure to output :email but fully-qualified nickname may serve as safe stub
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
|||
"pleroma_chat_messages",
|
||||
if Config.get([:instance, :show_reactions]) do
|
||||
"exposable_reactions"
|
||||
end,
|
||||
if Config.get([:instance, :profile_directory]) do
|
||||
"profile_directory"
|
||||
end
|
||||
]
|
||||
|> Enum.filter(& &1)
|
||||
|
|
|
|||
|
|
@ -600,6 +600,8 @@ defmodule Pleroma.Web.Router do
|
|||
get("/timelines/tag/:tag", TimelineController, :hashtag)
|
||||
|
||||
get("/polls/:id", PollController, :show)
|
||||
|
||||
get("/directory", DirectoryController, :index)
|
||||
end
|
||||
|
||||
scope "/api/v2", Pleroma.Web.MastodonAPI do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue