Merge branch 'masto-api-followers-following' into 'develop'
MastoAPI followers/following endpoints See merge request pleroma/pleroma!924
This commit is contained in:
commit
c231ed610a
3 changed files with 151 additions and 4 deletions
|
@ -1 +1,63 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
|
||||
@default_limit 20
|
||||
|
||||
def get_followers(user, params \\ %{}) do
|
||||
user
|
||||
|> User.get_followers_query()
|
||||
|> paginate(params)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def get_friends(user, params \\ %{}) do
|
||||
user
|
||||
|> User.get_friends_query()
|
||||
|> paginate(params)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def paginate(query, params \\ %{}) do
|
||||
options = cast_params(params)
|
||||
|
||||
query
|
||||
|> restrict(:max_id, options)
|
||||
|> restrict(:since_id, options)
|
||||
|> restrict(:limit, options)
|
||||
|> order_by([u], fragment("? desc nulls last", u.id))
|
||||
end
|
||||
|
||||
def cast_params(params) do
|
||||
param_types = %{
|
||||
max_id: :string,
|
||||
since_id: :string,
|
||||
limit: :integer
|
||||
}
|
||||
|
||||
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||
changeset.changes
|
||||
end
|
||||
|
||||
defp restrict(query, :max_id, %{max_id: max_id}) do
|
||||
query
|
||||
|> where([q], q.id < ^max_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :since_id, %{since_id: since_id}) do
|
||||
query
|
||||
|> where([q], q.id > ^since_id)
|
||||
end
|
||||
|
||||
defp restrict(query, :limit, options) do
|
||||
limit = Map.get(options, :limit, @default_limit)
|
||||
|
||||
query
|
||||
|> limit(^limit)
|
||||
end
|
||||
|
||||
defp restrict(query, _, _), do: query
|
||||
end
|
||||
|
|
|
@ -22,6 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.MastodonAPI.ReportView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
@ -652,9 +653,9 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do
|
|||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||
end
|
||||
|
||||
def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||
def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
||||
with %User{} = user <- Repo.get(User, id),
|
||||
{:ok, followers} <- User.get_followers(user) do
|
||||
followers <- MastodonAPI.get_followers(user, params) do
|
||||
followers =
|
||||
cond do
|
||||
for_user && user.id == for_user.id -> followers
|
||||
|
@ -663,14 +664,15 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
conn
|
||||
|> add_link_headers(:followers, followers, user)
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", %{users: followers, as: :user})
|
||||
end
|
||||
end
|
||||
|
||||
def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||
def following(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
||||
with %User{} = user <- Repo.get(User, id),
|
||||
{:ok, followers} <- User.get_friends(user) do
|
||||
followers <- MastodonAPI.get_friends(user, params) do
|
||||
followers =
|
||||
cond do
|
||||
for_user && user.id == for_user.id -> followers
|
||||
|
@ -679,6 +681,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
conn
|
||||
|> add_link_headers(:following, followers, user)
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", %{users: followers, as: :user})
|
||||
end
|
||||
|
|
|
@ -1195,6 +1195,47 @@ test "getting followers, hide_followers, same user requesting", %{conn: conn} do
|
|||
refute [] == json_response(conn, 200)
|
||||
end
|
||||
|
||||
test "getting followers, pagination", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
follower1 = insert(:user)
|
||||
follower2 = insert(:user)
|
||||
follower3 = insert(:user)
|
||||
{:ok, _} = User.follow(follower1, user)
|
||||
{:ok, _} = User.follow(follower2, user)
|
||||
{:ok, _} = User.follow(follower3, user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
|
||||
|
||||
assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
|
||||
assert id3 == follower3.id
|
||||
assert id2 == follower2.id
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
|
||||
|
||||
assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
|
||||
assert id2 == follower2.id
|
||||
assert id1 == follower1.id
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
|
||||
|
||||
assert [%{"id" => id2}] = json_response(res_conn, 200)
|
||||
assert id2 == follower2.id
|
||||
|
||||
assert [link_header] = get_resp_header(res_conn, "link")
|
||||
assert link_header =~ ~r/since_id=#{follower2.id}/
|
||||
assert link_header =~ ~r/max_id=#{follower2.id}/
|
||||
end
|
||||
|
||||
test "getting following", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
@ -1233,6 +1274,47 @@ test "getting following, hide_follows, same user requesting", %{conn: conn} do
|
|||
refute [] == json_response(conn, 200)
|
||||
end
|
||||
|
||||
test "getting following, pagination", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
following1 = insert(:user)
|
||||
following2 = insert(:user)
|
||||
following3 = insert(:user)
|
||||
{:ok, _} = User.follow(user, following1)
|
||||
{:ok, _} = User.follow(user, following2)
|
||||
{:ok, _} = User.follow(user, following3)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
|
||||
|
||||
assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
|
||||
assert id3 == following3.id
|
||||
assert id2 == following2.id
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
|
||||
|
||||
assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
|
||||
assert id2 == following2.id
|
||||
assert id1 == following1.id
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
|
||||
|
||||
assert [%{"id" => id2}] = json_response(res_conn, 200)
|
||||
assert id2 == following2.id
|
||||
|
||||
assert [link_header] = get_resp_header(res_conn, "link")
|
||||
assert link_header =~ ~r/since_id=#{following2.id}/
|
||||
assert link_header =~ ~r/max_id=#{following2.id}/
|
||||
end
|
||||
|
||||
test "following / unfollowing a user", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
Loading…
Reference in a new issue