1a4238bf98
Since those old migrations will now most likely only run during db init, there’s not much point in running them in the background concurrently anyway, so just drop the cncurrent setting rather than disabling migration locks.
112 lines
3.3 KiB
Elixir
112 lines
3.3 KiB
Elixir
defmodule Pleroma.Repo.Migrations.FixBlockedFollows do
|
|
use Ecto.Migration
|
|
|
|
import Ecto.Query
|
|
alias Pleroma.Config
|
|
alias Pleroma.Repo
|
|
|
|
def up do
|
|
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
|
|
|
|
if unfollow_blocked do
|
|
"activities"
|
|
|> where([activity], fragment("? ->> 'type' = 'Block'", activity.data))
|
|
|> distinct([activity], [
|
|
activity.actor,
|
|
fragment(
|
|
"coalesce((?)->'object'->>'id', (?)->>'object')",
|
|
activity.data,
|
|
activity.data
|
|
)
|
|
])
|
|
|> order_by([activity], [fragment("? desc nulls last", activity.id)])
|
|
|> select([activity], %{
|
|
blocker: activity.actor,
|
|
blocked:
|
|
fragment("coalesce((?)->'object'->>'id', (?)->>'object')", activity.data, activity.data),
|
|
created_at: activity.id
|
|
})
|
|
|> Repo.stream()
|
|
|> Enum.map(&unfollow_if_blocked/1)
|
|
|> Enum.uniq()
|
|
|> Enum.each(&update_follower_count/1)
|
|
end
|
|
end
|
|
|
|
def down do
|
|
end
|
|
|
|
def unfollow_if_blocked(%{blocker: blocker_id, blocked: blocked_id, created_at: blocked_at}) do
|
|
query =
|
|
from(
|
|
activity in "activities",
|
|
where: fragment("? ->> 'type' = 'Follow'", activity.data),
|
|
where: activity.actor == ^blocked_id,
|
|
# this is to use the index
|
|
where:
|
|
fragment(
|
|
"coalesce((?)->'object'->>'id', (?)->>'object') = ?",
|
|
activity.data,
|
|
activity.data,
|
|
^blocker_id
|
|
),
|
|
where: activity.id > ^blocked_at,
|
|
where: fragment("(?)->>'state' = 'accept'", activity.data),
|
|
order_by: [fragment("? desc nulls last", activity.id)]
|
|
)
|
|
|
|
unless Repo.exists?(query) do
|
|
blocker = "users" |> select([:id, :local]) |> Repo.get_by(ap_id: blocker_id)
|
|
blocked = "users" |> select([:id]) |> Repo.get_by(ap_id: blocked_id)
|
|
|
|
if !is_nil(blocker) && !is_nil(blocked) do
|
|
unfollow(blocked, blocker)
|
|
end
|
|
end
|
|
end
|
|
|
|
def unfollow(%{id: follower_id}, %{id: followed_id} = followed) do
|
|
following_relationship =
|
|
"following_relationships"
|
|
|> where(follower_id: ^follower_id, following_id: ^followed_id, state: "accept")
|
|
|> select([:id])
|
|
|> Repo.one()
|
|
|
|
case following_relationship do
|
|
nil ->
|
|
{:ok, nil}
|
|
|
|
%{id: following_relationship_id} ->
|
|
"following_relationships"
|
|
|> where(id: ^following_relationship_id)
|
|
|> Repo.delete_all()
|
|
|
|
followed
|
|
end
|
|
end
|
|
|
|
def update_follower_count(%{id: user_id} = user) do
|
|
if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
|
|
follower_count_query =
|
|
"users"
|
|
|> where([u], u.id != ^user_id)
|
|
|> where([u], u.deactivated != ^true)
|
|
|> join(:inner, [u], r in "following_relationships",
|
|
as: :relationships,
|
|
on: r.following_id == ^user_id and r.follower_id == u.id
|
|
)
|
|
|> where([relationships: r], r.state == "accept")
|
|
|> select([u], %{count: count(u.id)})
|
|
|
|
"users"
|
|
|> where(id: ^user_id)
|
|
|> join(:inner, [u], s in subquery(follower_count_query), on: true)
|
|
|> update([u, s],
|
|
set: [follower_count: s.count]
|
|
)
|
|
|> Repo.update_all([])
|
|
end
|
|
end
|
|
|
|
def update_follower_count(_), do: :noop
|
|
end
|