diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 693c9547c..34afbc699 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -553,6 +553,43 @@ module Mastodon end end + option :concurrency, type: :numeric, default: 5, aliases: [:c] + option :dry_run, type: :boolean + desc 'prune', 'Prune remote accounts that never interacted with local users' + long_desc <<-LONG_DESC + Prune remote account that + - follows no local accounts + - is not followed by any local accounts + - has no statuses on local + - has not been mentioned + - has not been favourited local posts + - not muted/blocked by us + LONG_DESC + def prune + dry_run = options[:dry_run] ? ' (dry run)' : '' + + query = Account.remote.where.not(actor_type: %i(Application Service)) + query = query.where('NOT EXISTS (SELECT 1 FROM mentions WHERE account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM favourites WHERE account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM statuses WHERE account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM follows WHERE account_id = accounts.id OR target_account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM blocks WHERE account_id = accounts.id OR target_account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM mutes WHERE target_account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM reports WHERE target_account_id = accounts.id)') + query = query.where('NOT EXISTS (SELECT 1 FROM follow_requests WHERE account_id = accounts.id OR target_account_id = accounts.id)') + + _, deleted = parallelize_with_progress(query) do |account| + next if account.bot? || account.group? + next if account.suspended? + next if account.silenced? + + account.destroy unless options[:dry_run] + 1 + end + + say("OK, pruned #{deleted} accounts#{dry_run}", :green) + end + option :force, type: :boolean option :replay, type: :boolean option :target