X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;ds=inline;f=lib%2Fpleroma%2Ffollowing_relationship.ex;h=9e75458e52c411c2ba8b23f8fa6ec82b605c54e9;hb=9e8e7cc13ebd2ec2ecbf90ae10c3532f77af7a81;hp=9ccf4049571f4303f8e952874dd4e940572f2eff;hpb=252528a4b9ca3a5d92f1676c44989ad7d8777de1;p=akkoma
diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex
index 9ccf40495..9e75458e5 100644
--- a/lib/pleroma/following_relationship.ex
+++ b/lib/pleroma/following_relationship.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
+# Copyright © 2017-2021 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.FollowingRelationship do
@@ -10,11 +10,14 @@ defmodule Pleroma.FollowingRelationship do
alias Ecto.Changeset
alias FlakeId.Ecto.CompatType
+ alias Pleroma.FollowingRelationship.State
alias Pleroma.Repo
alias Pleroma.User
+ @type follow_state :: :follow_pending | :follow_accept | :follow_reject | :unfollow
+
schema "following_relationships" do
- field(:state, Pleroma.FollowingRelationship.State, default: :follow_pending)
+ field(:state, State, default: :follow_pending)
belongs_to(:follower, User, type: CompatType)
belongs_to(:following, User, type: CompatType)
@@ -22,6 +25,11 @@ defmodule Pleroma.FollowingRelationship do
timestamps()
end
+ @doc "Returns underlying integer code for state atom"
+ def state_int_code(state_atom), do: State.__enum_map__() |> Keyword.fetch!(state_atom)
+
+ def accept_state_code, do: state_int_code(:follow_accept)
+
def changeset(%__MODULE__{} = following_relationship, attrs) do
following_relationship
|> cast(attrs, [:state])
@@ -56,23 +64,53 @@ defmodule Pleroma.FollowingRelationship do
follow(follower, following, state)
following_relationship ->
- following_relationship
- |> cast(%{state: state}, [:state])
- |> validate_required([:state])
- |> Repo.update()
+ with {:ok, _following_relationship} <-
+ following_relationship
+ |> cast(%{state: state}, [:state])
+ |> validate_required([:state])
+ |> Repo.update() do
+ after_update(state, follower, following)
+ end
end
end
+ @spec follow(User.t(), User.t()) :: {:ok, User.t(), User.t()} | {:error, any}
def follow(%User{} = follower, %User{} = following, state \\ :follow_accept) do
- %__MODULE__{}
- |> changeset(%{follower: follower, following: following, state: state})
- |> Repo.insert(on_conflict: :nothing)
+ with {:ok, _following_relationship} <-
+ %__MODULE__{}
+ |> changeset(%{follower: follower, following: following, state: state})
+ |> Repo.insert(on_conflict: :nothing) do
+ after_update(state, follower, following)
+ end
end
+ @spec unfollow(User.t(), User.t()) :: {:ok, User.t(), User.t()} | {:error, any}
def unfollow(%User{} = follower, %User{} = following) do
case get(follower, following) do
- %__MODULE__{} = following_relationship -> Repo.delete(following_relationship)
- _ -> {:ok, nil}
+ %__MODULE__{} = following_relationship ->
+ with {:ok, _following_relationship} <- Repo.delete(following_relationship) do
+ after_update(:unfollow, follower, following)
+ end
+
+ _ ->
+ {:ok, follower, following}
+ end
+ end
+
+ @spec after_update(follow_state(), User.t(), User.t()) ::
+ {:ok, User.t(), User.t()} | {:error, any()}
+ defp after_update(state, %User{} = follower, %User{} = following) do
+ with {:ok, following} <- User.update_follower_count(following),
+ {:ok, follower} <- User.update_following_count(follower) do
+ Pleroma.Web.Streamer.stream("follow_relationship", %{
+ state: state,
+ following: following,
+ follower: follower
+ })
+
+ {:ok, follower, following}
+ else
+ err -> {:error, err}
end
end
@@ -82,6 +120,33 @@ defmodule Pleroma.FollowingRelationship do
|> Repo.aggregate(:count, :id)
end
+ def followers_query(%User{} = user) do
+ __MODULE__
+ |> join(:inner, [r], u in User, on: r.follower_id == u.id)
+ |> where([r], r.following_id == ^user.id)
+ |> where([r], r.state == ^:follow_accept)
+ end
+
+ def followers_ap_ids(user, from_ap_ids \\ nil)
+
+ def followers_ap_ids(_, []), do: []
+
+ def followers_ap_ids(%User{} = user, from_ap_ids) do
+ query =
+ user
+ |> followers_query()
+ |> select([r, u], u.ap_id)
+
+ query =
+ if from_ap_ids do
+ where(query, [r, u], u.ap_id in ^from_ap_ids)
+ else
+ query
+ end
+
+ Repo.all(query)
+ end
+
def following_count(%User{id: nil}), do: 0
def following_count(%User{} = user) do
@@ -90,13 +155,13 @@ defmodule Pleroma.FollowingRelationship do
|> Repo.aggregate(:count, :id)
end
- def get_follow_requests(%User{id: id}) do
+ def get_follow_requests_query(%User{id: id}) do
__MODULE__
- |> join(:inner, [r], f in assoc(r, :follower))
+ |> join(:inner, [r], f in assoc(r, :follower), as: :follower)
|> where([r], r.state == ^:follow_pending)
|> where([r], r.following_id == ^id)
- |> select([r, f], f)
- |> Repo.all()
+ |> where([r, follower: f], f.is_active == true)
+ |> select([r, follower: f], f)
end
def following?(%User{id: follower_id}, %User{id: followed_id}) do
@@ -105,12 +170,22 @@ defmodule Pleroma.FollowingRelationship do
|> Repo.exists?()
end
+ def following_query(%User{} = user) do
+ __MODULE__
+ |> join(:inner, [r], u in User, on: r.following_id == u.id)
+ |> where([r], r.follower_id == ^user.id)
+ |> where([r], r.state == ^:follow_accept)
+ end
+
+ def outgoing_pending_follow_requests_query(%User{} = follower) do
+ __MODULE__
+ |> where([r], r.follower_id == ^follower.id)
+ |> where([r], r.state == ^:follow_pending)
+ end
+
def following(%User{} = user) do
following =
- __MODULE__
- |> join(:inner, [r], u in User, on: r.following_id == u.id)
- |> where([r], r.follower_id == ^user.id)
- |> where([r], r.state == ^:follow_accept)
+ following_query(user)
|> select([r, u], u.follower_address)
|> Repo.all()
@@ -126,12 +201,13 @@ defmodule Pleroma.FollowingRelationship do
|> join(:inner, [r], f in assoc(r, :follower))
|> where(following_id: ^origin.id)
|> where([r, f], f.allow_following_move == true)
+ |> where([r, f], f.local == true)
|> limit(50)
|> preload([:follower])
|> Repo.all()
|> Enum.map(fn following_relationship ->
- Repo.delete(following_relationship)
Pleroma.Web.CommonAPI.follow(following_relationship.follower, target)
+ Pleroma.Web.CommonAPI.unfollow(following_relationship.follower, origin)
end)
|> case do
[] ->
@@ -196,4 +272,12 @@ defmodule Pleroma.FollowingRelationship do
end
end)
end
+
+ @spec following_ap_ids(User.t()) :: [String.t()]
+ def following_ap_ids(%User{} = user) do
+ user
+ |> following_query()
+ |> select([r, u], u.ap_id)
+ |> Repo.all()
+ end
end