forked from YokaiRick/akkoma
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.MastodonView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MastodonAPI.ReportView
|
alias Pleroma.Web.MastodonAPI.ReportView
|
||||||
|
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
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})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
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),
|
with %User{} = user <- Repo.get(User, id),
|
||||||
{:ok, followers} <- User.get_followers(user) do
|
followers <- MastodonAPI.get_followers(user, params) do
|
||||||
followers =
|
followers =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> followers
|
for_user && user.id == for_user.id -> followers
|
||||||
|
@ -663,14 +664,15 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|
|> add_link_headers(:followers, followers, user)
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{users: followers, as: :user})
|
|> render("accounts.json", %{users: followers, as: :user})
|
||||||
end
|
end
|
||||||
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),
|
with %User{} = user <- Repo.get(User, id),
|
||||||
{:ok, followers} <- User.get_friends(user) do
|
followers <- MastodonAPI.get_friends(user, params) do
|
||||||
followers =
|
followers =
|
||||||
cond do
|
cond do
|
||||||
for_user && user.id == for_user.id -> followers
|
for_user && user.id == for_user.id -> followers
|
||||||
|
@ -679,6 +681,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|
|> add_link_headers(:following, followers, user)
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{users: followers, as: :user})
|
|> render("accounts.json", %{users: followers, as: :user})
|
||||||
end
|
end
|
||||||
|
|
|
@ -1195,6 +1195,47 @@ test "getting followers, hide_followers, same user requesting", %{conn: conn} do
|
||||||
refute [] == json_response(conn, 200)
|
refute [] == json_response(conn, 200)
|
||||||
end
|
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
|
test "getting following", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_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)
|
refute [] == json_response(conn, 200)
|
||||||
end
|
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
|
test "following / unfollowing a user", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
Loading…
Reference in a new issue