# Federated Computer, Inc. # David Sainty 2024 A.D. # Gossamer Threads to Discourse -- Soft Deletion of Marked-As-Deleted Posts # v0.3 Ready for actual soft-delete run on live-prod require 'mysql2' require 'active_record' # require 'concurrent-ruby' require File.expand_path("../../../../config/environment", __FILE__) require File.expand_path("../../../../script/import_scripts/base", __FILE__) class GossamerForumsSoftDelDeletedPosts < ImportScripts::Base def initialize super begin # Initialize MySQL client to connect to Gossamer Forums database @mysql_client = Mysql2::Client.new( host: "slowtwitch.northend.network", username: "admin", password: "yxnh93Ybbz2Nm8#mp28zCVv", database: "slowtwitch" ) rescue Mysql2::Error => e puts "Error connecting to MySQL: #{e.message}" exit 1 end end # Define a method to find a post by custom field def find_post_by_custom_field(post_id) puts "SoftDelDeletedPosts: Searching for post with original_gossamer_id: #{post_id}" post_custom_field = PostCustomField.find_by(name: 'original_gossamer_id', value: post_id.to_s) if post_custom_field post = post_custom_field.post puts "SoftDelDeletedPosts: Found post with id: #{post.id}" post else puts "SoftDelDeletedPosts: No post found with original_gossamer_id: #{post_id}" nil end end # Soft delete the post, whether topic post (OP) or reply post def soft_delete_post(post, deleted_by_id) if post.deleted_at.nil? # # Get the post's owner and topic information # user = User.find_by(id: post.user_id) # Fetch user details # topic = Topic.find_by(id: post.topic_id) # Fetch topic details # # Display post, user, and topic information # puts "DELETING POST: SoftDelDeletedPosts: Soft deleting post with id: #{post.id}" # puts " - Post owner: #{user.username} (ID: #{user.id})" # puts " - Topic title: '#{topic.title}' (Topic ID: #{topic.id})" # Perform the soft delete by updating the fields ## post.deleted_at = Time.now ## post.deleted_by_id = deleted_by_id ## post.save puts "... actual deleted_at step" post.update(deleted_at: Time.now, deleted_by_id: deleted_by_id) else puts "SoftDelDeletedPosts: Post with id: #{post.id} is already soft deleted." end end # Define the method to delete posts based on the Gossamer Forums flag def soft_del_deleted_posts_from_gossamer_with_user(username) # Query the user ID from the legacy MySQL database user_result = @mysql_client.query("SELECT user_id FROM gforum_User WHERE user_username = '#{username}' LIMIT 1") user_id_row = user_result.first if user_id_row.nil? puts "DiscourseDeletedPosts: No user found with username: #{username}" return end user_id = user_id_row['user_id'] # Find all posts marked as deleted by the given user posts_result = @mysql_client.query("SELECT post_id FROM gforum_Post WHERE post_deleted = 1 AND user_id_fk = #{user_id}") # "admin" user is ID 1, so set as the one performing the deletions deleted_by_id = 1 posts_result.each do |legacy_post| post_id = legacy_post['post_id'] # Look for the post in Discourse by custom field post = find_post_by_custom_field(post_id) if post # Soft delete only the individual post (whether topic post / OP or a reply post) soft_delete_post(post, deleted_by_id) end end end # Define the method to reverse (soft undelete) the soft deletion def soft_undelete_post(post) if post.deleted_at.present? # Get the post's owner and topic information user = User.find_by(id: post.user_id) # Fetch user details topic = Topic.find_by(id: post.topic_id) # Fetch topic details # Display post, user, and topic information puts "RESTORING POST: SoftDelDeletedPosts: Soft undeleting post with id: #{post.id}" puts " - Post owner: #{user.username} (ID: #{user.id})" puts " - Topic title: '#{topic.title}' (Topic ID: #{topic.id})" # Reverse the soft delete by setting deleted_at and deleted_by_id to nil ### post.update(deleted_at: nil, deleted_by_id: nil) else puts "SoftDelDeletedPosts: Post with id: #{post.id} is not soft deleted." end end # Define the method to reverse the soft deletion for all legacy posts def soft_undelete_all_deleted_posts # Query the legacy database for posts marked as deleted posts_result = @mysql_client.query("SELECT post_id FROM gforum_Post WHERE post_deleted = 1") posts_result.each do |legacy_post| post_id = legacy_post['post_id'] # Look for the post in Discourse by custom field post = find_post_by_custom_field(post_id) if post # Reverse the soft deletion (restore the post) soft_undelete_post(post) end end end # Define the method to delete posts based on the Gossamer Forums flag def soft_del_all_deleted_posts # Find all posts marked as deleted by the given user posts_result = @mysql_client.query("SELECT post_id FROM gforum_Post WHERE post_deleted = 1") # "admin" user is ID 1, so set as the one performing the deletions deleted_by_id = 1 posts_result.each do |legacy_post| post_id = legacy_post['post_id'] # # Look for the post in Discourse by custom field # post = find_post_by_custom_field(post_id) # # if post # # Soft delete only the individual post (whether topic post / OP or a reply post) # soft_delete_post(post, deleted_by_id) # end soft_del_all_deleted_posts_by_custom_field(post_id, deleted_by_id) end end # Define a method to find all posts by the original Gossamer Forums post ID and soft delete them def soft_del_all_deleted_posts_by_custom_field(post_id, deleted_by_id) puts "SoftDelDeletedPosts: Searching for all posts with original_gossamer_id: #{post_id}" # Find all PostCustomField records with the given Gossamer Forums post_id post_custom_fields = PostCustomField.where(name: 'original_gossamer_id', value: post_id.to_s) if post_custom_fields.any? post_custom_fields.each do |post_custom_field| post = post_custom_field.post if post puts "DELETING POST: SoftDelDeletedPosts: Soft deleting post with id: #{post.id} and user_id: #{post.user_id} and topic_id: #{post.topic_id}" # Get the post's owner and topic information # user = User.find_by(id: post.user_id) # Fetch user details # topic = Topic.find_by(id: post.topic_id) # Fetch topic details # Display post, user, and topic information # puts " - Post owner: #{user.username} (ID: #{user.id})" # puts " - Topic title: '#{topic.title}' (Topic ID: #{topic.id})" # Soft delete the post if not already deleted soft_delete_post(post, deleted_by_id) else puts "SoftDelDeletedPosts: Found PostCustomField with no corresponding post (ID: #{post_custom_field.id})" end end else puts "SoftDelDeletedPosts: No PostCustomField records found with original_gossamer_id: #{post_id}" end end def perform_deleted_soft_del puts "Soft Del Deleted Posts beginning!" ## soft_del_deleted_posts_from_gossamer_with_user('spudone') ## soft_undelete_all_deleted_posts soft_del_all_deleted_posts puts "Soft Del Deleted Posts complete!" end end GossamerForumsSoftDelDeletedPosts.new.perform_deleted_soft_del