# Federated Computer, Inc. # David Sainty 2024 A.D. # Gossamer Threads to Discourse -- CleanUp Script # v0.17 Add more cleanup options. require 'concurrent-ruby' require File.expand_path("../../../../config/environment", __FILE__) class GossamerForumsCleaner def cleanup_users puts "Cleaning up imported users..." # Find all users imported from Gossamer Forums and delete them UserCustomField.where(name: 'original_gossamer_id').each do |field| user = User.find_by(id: field.user_id) if user puts "Deleting user #{user.username} (ID: #{user.id})" user.destroy end end end def cleanup_categories puts "Cleaning up imported categories..." # Find all categories that were imported and delete them CategoryCustomField.where(name: 'original_gossamer_id').each do |field| category = Category.find_by(id: field.category_id) if category puts "Deleting category #{category.name} (ID: #{category.id})" category.destroy end end end def cleanup_topics puts "Cleaning up imported topics..." # Find all topics that were imported and delete them TopicCustomField.where(name: 'original_gossamer_id').each do |field| topic = Topic.find_by(id: field.topic_id) if topic puts "Deleting topic #{topic.title} (ID: #{topic.id})" # topic.posts.each do |post| # puts "Deleting post #{post.id} in topic #{topic.id}" # post.destroy # end topic.destroy end end end def cleanup_topics_former_user puts "Cleaning up imported topics..." # Find all topics that were imported TopicCustomField.where(name: 'original_gossamer_id').each do |field| topic = Topic.find_by(id: field.topic_id) next unless topic # Fetch the first post in the topic first_post = topic.posts.order(:created_at).first # Check if the first post has user_id 2 if first_post && first_post.user_id == 2 puts "Deleting topic #{topic.title} (ID: #{topic.id})" # Destroy all posts in the topic topic.posts.each do |post| puts "Deleting post #{post.id} in topic #{topic.id}" post.destroy end # Destroy the topic itself topic.destroy end end end def cleanup_topics_with_invalid_posts_count puts "Cleaning up topics with invalid posts_count..." # Iterate through all topics Topic.where("posts_count IS NULL OR posts_count = -1 OR posts_count = 0").find_each do |topic| puts "Identified topic for deletion: Title: #{topic.title} Topic ID: #{topic.id}" # Destroy all posts in the topic topic.posts.each do |post| puts "Deleting post #{post.id} in topic #{topic.id}" post.destroy end # Destroy the topic itself topic.destroy end end def cleanup_posts puts "Cleaning up imported posts..." # Find all posts that were imported and delete them PostCustomField.where(name: 'original_gossamer_id').each do |field| post = Post.find_by(id: field.post_id) if post puts "Deleting post #{post.id} (ID: #{post.id})" post.destroy end end end def cleanup_posts_parallel puts "Cleaning up imported posts..." # Define the number of threads to use num_threads = 8 pool = Concurrent::FixedThreadPool.new(num_threads) PostCustomField.where(name: 'original_gossamer_id').in_batches(of: 1000) do |batch| batch.each do |field| pool.post do post = Post.find_by(id: field.post_id) if post puts "Deleting post #{post.id} (ID: #{post.id})" post.destroy end end end end # Wait for all threads to complete pool.shutdown pool.wait_for_termination end def cleanup_messages puts "Cleaning up imported personal messages..." # Find all personal messages (inbox) that were imported and delete them TopicCustomField.where(name: 'original_gossamer_msg_id').each do |field| topic = Topic.find_by(id: field.topic_id) if topic puts "Deleting personal message topic #{topic.title} (ID: #{topic.id})" topic.posts.each do |post| puts "Deleting post #{post.id} in personal message topic #{topic.id}" post.destroy end topic.destroy end end end def perform_cleanup puts "Cleanup beginning!" # cleanup_messages # cleanup_topics # cleanup_topics_former_user cleanup_topics_with_invalid_posts_count # cleanup_posts_parallel # cleanup_categories # cleanup_users puts "Cleanup complete!" end end GossamerForumsCleaner.new.perform_cleanup