+
+ def move_following(origin, target) do
+ __MODULE__
+ |> join(:inner, [r], f in assoc(r, :follower))
+ |> where(following_id: ^origin.id)
+ |> where([r, f], f.allow_following_move == true)
+ |> limit(50)
+ |> preload([:follower])
+ |> Repo.all()
+ |> Enum.map(fn following_relationship ->
+ Repo.delete(following_relationship)
+ Pleroma.Web.CommonAPI.follow(following_relationship.follower, target)
+ end)
+ |> case do
+ [] ->
+ User.update_follower_count(origin)
+ :ok
+
+ _ ->
+ move_following(origin, target)
+ end
+ end
+
+ def all_between_user_sets(
+ source_users,
+ target_users
+ )
+ when is_list(source_users) and is_list(target_users) do
+ source_user_ids = User.binary_id(source_users)
+ target_user_ids = User.binary_id(target_users)
+
+ __MODULE__
+ |> where(
+ fragment(
+ "(follower_id = ANY(?) AND following_id = ANY(?)) OR \
+ (follower_id = ANY(?) AND following_id = ANY(?))",
+ ^source_user_ids,
+ ^target_user_ids,
+ ^target_user_ids,
+ ^source_user_ids
+ )
+ )
+ |> Repo.all()
+ end
+
+ def find(following_relationships, follower, following) do
+ Enum.find(following_relationships, fn
+ fr -> fr.follower_id == follower.id and fr.following_id == following.id
+ end)
+ end
+
+ defp validate_not_self_relationship(%Changeset{} = changeset) do
+ changeset
+ |> validate_follower_id_following_id_inequality()
+ |> validate_following_id_follower_id_inequality()
+ end
+
+ defp validate_follower_id_following_id_inequality(%Changeset{} = changeset) do
+ validate_change(changeset, :follower_id, fn _, follower_id ->
+ if follower_id == get_field(changeset, :following_id) do
+ [source_id: "can't be equal to following_id"]
+ else
+ []
+ end
+ end)
+ end
+
+ defp validate_following_id_follower_id_inequality(%Changeset{} = changeset) do
+ validate_change(changeset, :following_id, fn _, following_id ->
+ if following_id == get_field(changeset, :follower_id) do
+ [target_id: "can't be equal to follower_id"]
+ else
+ []
+ end
+ end)
+ end