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.

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