cli.rb 4.4 KB

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