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.

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