You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.9 KiB

  1. # frozen_string_literal: true
  2. require 'thor'
  3. require_relative 'mastodon/media_cli'
  4. require_relative 'mastodon/emoji_cli'
  5. require_relative 'mastodon/accounts_cli'
  6. require_relative 'mastodon/feeds_cli'
  7. require_relative 'mastodon/search_cli'
  8. require_relative 'mastodon/settings_cli'
  9. require_relative 'mastodon/statuses_cli'
  10. require_relative 'mastodon/domains_cli'
  11. require_relative 'mastodon/preview_cards_cli'
  12. require_relative 'mastodon/cache_cli'
  13. require_relative 'mastodon/upgrade_cli'
  14. require_relative 'mastodon/email_domain_blocks_cli'
  15. require_relative 'mastodon/canonical_email_blocks_cli'
  16. require_relative 'mastodon/ip_blocks_cli'
  17. require_relative 'mastodon/maintenance_cli'
  18. require_relative 'mastodon/version'
  19. module Mastodon
  20. class CLI < Thor
  21. def self.exit_on_failure?
  22. true
  23. end
  24. desc 'media SUBCOMMAND ...ARGS', 'Manage media files'
  25. subcommand 'media', Mastodon::MediaCLI
  26. desc 'emoji SUBCOMMAND ...ARGS', 'Manage custom emoji'
  27. subcommand 'emoji', Mastodon::EmojiCLI
  28. desc 'accounts SUBCOMMAND ...ARGS', 'Manage accounts'
  29. subcommand 'accounts', Mastodon::AccountsCLI
  30. desc 'feeds SUBCOMMAND ...ARGS', 'Manage feeds'
  31. subcommand 'feeds', Mastodon::FeedsCLI
  32. desc 'search SUBCOMMAND ...ARGS', 'Manage the search engine'
  33. subcommand 'search', Mastodon::SearchCLI
  34. desc 'settings SUBCOMMAND ...ARGS', 'Manage dynamic settings'
  35. subcommand 'settings', Mastodon::SettingsCLI
  36. desc 'statuses SUBCOMMAND ...ARGS', 'Manage statuses'
  37. subcommand 'statuses', Mastodon::StatusesCLI
  38. desc 'domains SUBCOMMAND ...ARGS', 'Manage account domains'
  39. subcommand 'domains', Mastodon::DomainsCLI
  40. desc 'preview_cards SUBCOMMAND ...ARGS', 'Manage preview cards'
  41. subcommand 'preview_cards', Mastodon::PreviewCardsCLI
  42. desc 'cache SUBCOMMAND ...ARGS', 'Manage cache'
  43. subcommand 'cache', Mastodon::CacheCLI
  44. desc 'upgrade SUBCOMMAND ...ARGS', 'Various version upgrade utilities'
  45. subcommand 'upgrade', Mastodon::UpgradeCLI
  46. desc 'email_domain_blocks SUBCOMMAND ...ARGS', 'Manage e-mail domain blocks'
  47. subcommand 'email_domain_blocks', Mastodon::EmailDomainBlocksCLI
  48. desc 'ip_blocks SUBCOMMAND ...ARGS', 'Manage IP blocks'
  49. subcommand 'ip_blocks', Mastodon::IpBlocksCLI
  50. desc 'canonical_email_blocks SUBCOMMAND ...ARGS', 'Manage canonical e-mail blocks'
  51. subcommand 'canonical_email_blocks', Mastodon::CanonicalEmailBlocksCLI
  52. desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities'
  53. subcommand 'maintenance', Mastodon::MaintenanceCLI
  54. option :dry_run, type: :boolean
  55. desc 'self-destruct', 'Erase the server from the federation'
  56. long_desc <<~LONG_DESC
  57. Erase the server from the federation by broadcasting account delete
  58. activities to all known other servers. This allows a "clean exit" from
  59. running a Mastodon server, as it leaves next to no cache behind on
  60. other servers.
  61. This command is always interactive and requires confirmation twice.
  62. No local data is actually deleted, because emptying the
  63. database or removing files is much faster through other, external
  64. means, such as e.g. deleting the entire VPS. However, because other
  65. servers will delete data about local users, but no local data will be
  66. updated (such as e.g. followers), there will be a state mismatch
  67. that will lead to glitches and issues if you then continue to run and use
  68. the server.
  69. So either you know exactly what you are doing, or you are starting
  70. from a blank slate afterwards by manually clearing out all the local
  71. data!
  72. LONG_DESC
  73. def self_destruct
  74. require 'tty-prompt'
  75. prompt = TTY::Prompt.new
  76. exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain
  77. unless options[:dry_run]
  78. prompt.warn('This operation WILL NOT be reversible. It can also take a long time.')
  79. prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.')
  80. prompt.warn('A running Sidekiq process is required. Do not shut it down until queues clear.')
  81. exit(1) if prompt.no?('Are you sure you want to proceed?')
  82. end
  83. inboxes = Account.inboxes
  84. processed = 0
  85. dry_run = options[:dry_run] ? ' (DRY RUN)' : ''
  86. Setting.registrations_mode = 'none' unless options[:dry_run]
  87. if inboxes.empty?
  88. Account.local.without_suspended.in_batches.update_all(suspended_at: Time.now.utc, suspension_origin: :local) unless options[:dry_run]
  89. prompt.ok('It seems like your server has not federated with anything')
  90. prompt.ok('You can shut it down and delete it any time')
  91. return
  92. end
  93. prompt.warn('Do NOT interrupt this process...')
  94. delete_account = ->(account) do
  95. payload = ActiveModelSerializers::SerializableResource.new(
  96. account,
  97. serializer: ActivityPub::DeleteActorSerializer,
  98. adapter: ActivityPub::Adapter
  99. ).as_json
  100. json = Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(account))
  101. unless options[:dry_run]
  102. ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
  103. [json, account.id, inbox_url]
  104. end
  105. account.suspend!(block_email: false)
  106. end
  107. processed += 1
  108. end
  109. Account.local.without_suspended.find_each { |account| delete_account.call(account) }
  110. Account.local.suspended.joins(:deletion_request).find_each { |account| delete_account.call(account) }
  111. prompt.ok("Queued #{inboxes.size * processed} items into Sidekiq for #{processed} accounts#{dry_run}")
  112. prompt.ok('Wait until Sidekiq processes all items, then you can shut everything down and delete the data')
  113. rescue TTY::Reader::InputInterrupt
  114. exit(1)
  115. end
  116. map %w(--version -v) => :version
  117. desc 'version', 'Show version'
  118. def version
  119. say(Mastodon::Version.to_s)
  120. end
  121. end
  122. end