mirror of
https://github.com/discourse/discourse.git
synced 2025-06-06 03:06:53 +08:00
DEV: Add rake task to bulk delete posts (#31642)
Same as #31576, but in that one I added some support files that turned out to be unnecessary and broke the build. So this is the re-do. 🙏
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "highline/import"
|
||||
|
||||
class DestroyTask
|
||||
def initialize(io = STDOUT)
|
||||
@io = io
|
||||
@ -46,6 +48,32 @@ class DestroyTask
|
||||
categories.each { |c| @io.puts destroy_topics(c.slug, c.parent_category&.slug) }
|
||||
end
|
||||
|
||||
def destroy_posts(post_ids, require_confirmation: true)
|
||||
posts = Post.with_deleted.where(id: post_ids)
|
||||
|
||||
@io.puts "There are #{posts.count} posts to delete"
|
||||
|
||||
if posts.count < post_ids.size
|
||||
@io.puts "Couldn't find the following posts:"
|
||||
@io.puts " #{post_ids.map(&:to_i) - posts.pluck(:id)}"
|
||||
end
|
||||
|
||||
if require_confirmation
|
||||
confirm_destroy = ask("Are you sure? (Y/n)")
|
||||
exit 1 if confirm_destroy.downcase != "y"
|
||||
end
|
||||
|
||||
posts.find_each do |post|
|
||||
@io.puts "Destroying post #{post.id}"
|
||||
@io.puts PostDestroyer.new(
|
||||
Discourse.system_user,
|
||||
post,
|
||||
context: I18n.t("staff_action_logs.cli_bulk_post_delete"),
|
||||
force_destroy: true,
|
||||
).destroy
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_private_messages
|
||||
Topic
|
||||
.where(archetype: "private_message")
|
||||
|
@ -5560,6 +5560,7 @@ en:
|
||||
revoked: Revoked
|
||||
restored: Restored
|
||||
bulk_user_delete: "deleted in a bulk delete operation"
|
||||
cli_bulk_post_delete: "Bulk deleted from rake task"
|
||||
|
||||
reviewables:
|
||||
already_handled: "Thanks, but we've already reviewed that post and determined it does not need to be flagged again."
|
||||
|
@ -50,3 +50,16 @@ task "destroy:categories" => :environment do |t, args|
|
||||
puts "Going to delete these categories: #{categories}"
|
||||
categories.each { |id| destroy_task.destroy_category(id, true) }
|
||||
end
|
||||
|
||||
# Hard delete a list of posts by ID. Pass a comma
|
||||
# separated list either as a rake argument or through
|
||||
# STDIN, e.g. through a pipe.
|
||||
#
|
||||
# Example: rake destroy:posts[4,8,15,16,23,42]
|
||||
# Example: cat post_ids.txt | rake destroy:posts
|
||||
desc "Destroy a list of posts given by ID"
|
||||
task "destroy:posts" => :environment do |_task, args|
|
||||
post_ids = args.extras.empty? ? STDIN.read.strip.split(",") : args.extras
|
||||
puts "Going to delete these posts: #{post_ids}"
|
||||
DestroyTask.new.destroy_posts(post_ids)
|
||||
end
|
||||
|
@ -67,6 +67,30 @@ RSpec.describe DestroyTask do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#destroy_posts" do
|
||||
let(:task) { DestroyTask.new(StringIO.new) }
|
||||
|
||||
let!(:t1) { Fabricate(:topic) }
|
||||
let!(:t2) { Fabricate(:topic) }
|
||||
|
||||
let!(:p1) { Fabricate(:post, topic: t1) }
|
||||
let!(:p2) { Fabricate(:post, topic: t1) }
|
||||
let!(:p3) { Fabricate(:post, topic: t2) }
|
||||
|
||||
before { p2.trash! }
|
||||
|
||||
it "destroys posts listed and creates staff action logs" do
|
||||
expect { task.destroy_posts([p2.id, p3.id], require_confirmation: false) }.to change {
|
||||
Post.with_deleted.count
|
||||
}.by(-2).and change { UserHistory.pluck(:action) }.from([]).to(
|
||||
[
|
||||
UserHistory.actions[:delete_post_permanently],
|
||||
UserHistory.actions[:delete_topic_permanently],
|
||||
],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "private messages" do
|
||||
let!(:pm) { Fabricate(:private_message_post) }
|
||||
let!(:pm2) { Fabricate(:private_message_post) }
|
||||
|
16
spec/tasks/destroy_spec.rb
Normal file
16
spec/tasks/destroy_spec.rb
Normal file
@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe "destroy:posts" do
|
||||
it "accepts a list of post IDs piped through STDIN" do
|
||||
destroy_task = instance_spy(DestroyTask)
|
||||
DestroyTask.stubs(:new).returns(destroy_task)
|
||||
|
||||
STDIN.stubs(:read).returns("1,2,3\n")
|
||||
|
||||
capture_stdout do
|
||||
invoke_rake_task("destroy:posts")
|
||||
|
||||
expect(destroy_task).to have_received(:destroy_posts).with(%w[1 2 3])
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user