about summary refs log tree commit diff
path: root/lib/mastodon/accounts_cli.rb
diff options
context:
space:
mode:
authorJeong Arm <kjwonmail@gmail.com>2023-01-14 06:34:16 +0900
committerGitHub <noreply@github.com>2023-01-13 22:34:16 +0100
commit0e8f8a1a1c225272596b3256e3adb0a20a0dc483 (patch)
treee2b3414963fe0e9163cc8df70ae09cb84bacc755 /lib/mastodon/accounts_cli.rb
parent507e1d22f580b23d47d8dc0cb47f6f0b3170fc56 (diff)
Implement tootctl accounts prune (#18397)
* Implement tootctl accounts prune

* Optimise query

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
Diffstat (limited to 'lib/mastodon/accounts_cli.rb')
-rw-r--r--lib/mastodon/accounts_cli.rb37
1 files changed, 37 insertions, 0 deletions
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