From cafe27fb29a5fbdd9edb08e94a7e47db8eadaf43 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 24 Dec 2017 16:14:33 +0100 Subject: [PATCH] Add rake task to check and purge accounts that are missing in origin (#6085) * Add rake task to check and purge accounts that are missing in origin * Add progress bar and --force options to mastodon:maintenance:purge_removed_accounts --- lib/tasks/mastodon.rake | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 0f2cc536a..33969d470 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -1,5 +1,8 @@ # frozen_string_literal: true +require 'optparse' +require 'colorize' + namespace :mastodon do desc 'Execute daily tasks (deprecated)' task :daily do @@ -338,5 +341,75 @@ namespace :mastodon do PreviewCard.where(embed_url: '', type: :photo).delete_all LinkCrawlWorker.push_bulk status_ids end + + desc 'Check every known remote account and delete those that no longer exist in origin' + task purge_removed_accounts: :environment do + prepare_for_options! + + options = {} + + OptionParser.new do |opts| + opts.banner = 'Usage: rails mastodon:maintenance:purge_removed_accounts [options]' + + opts.on('-f', '--force', 'Remove all encountered accounts without asking for confirmation') do + options[:force] = true + end + + opts.on('-h', '--help', 'Display this message') do + puts opts + exit + end + end.parse! + + disable_log_stdout! + + total = Account.remote.where(protocol: :activitypub).count + progress_bar = ProgressBar.create(total: total, format: '%c/%C |%w>%i| %e') + + Account.remote.where(protocol: :activitypub).partitioned.find_each do |account| + progress_bar.increment + + begin + res = Request.new(:head, account.uri).perform + rescue StandardError + # This could happen due to network timeout, DNS timeout, wrong SSL cert, etc, + # which should probably not lead to perceiving the account as deleted, so + # just skip till next time + next + end + + if [404, 410].include?(res.code) + if options[:force] + account.destroy + else + progress_bar.pause + progress_bar.clear + print "\nIt seems like #{account.acct} no longer exists. Purge the account from the database? [Y/n]: ".colorize(:yellow) + confirm = STDIN.gets.chomp + puts '' + progress_bar.resume + + if confirm.casecmp('n').zero? + next + else + account.destroy + end + end + end + end + end end end + +def disable_log_stdout! + dev_null = Logger.new('/dev/null') + + Rails.logger = dev_null + ActiveRecord::Base.logger = dev_null + HttpLog.configuration.logger = dev_null + Paperclip.options[:log] = false +end + +def prepare_for_options! + 2.times { ARGV.shift } +end