From a6d48e825d3324033d2caf9dff8d121bae38d7bc Mon Sep 17 00:00:00 2001 From: saint Date: Thu, 20 Jun 2024 01:13:08 +1000 Subject: [PATCH] v0.10 Add support for SQLite DB and CSV file generation for mapping of old to new usernames --- gossamer_forums.rb | 87 +++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/gossamer_forums.rb b/gossamer_forums.rb index 065558a..4bca310 100644 --- a/gossamer_forums.rb +++ b/gossamer_forums.rb @@ -1,9 +1,16 @@ +# gossamer threads migration-import code +# v0.10 + require 'mysql2' require 'open-uri' require 'net/http' require 'tempfile' require 'sqlite3' +require 'digest' +require 'fileutils' +require 'csv' + require File.expand_path("../../../config/environment", __FILE__) require_relative 'base' @@ -25,11 +32,11 @@ class GossamerForumsImporter < ImportScripts::Base # # Create a mapping of old Gossamer user IDs to new Discourse user IDs # @user_id_map = {} - initialize_sqlite_user_id_db + initialize_sqlite_id_name_url_db end - def initialize_sqlite_user_id_db - @db = SQLite3::Database.new 'user_id_map.db' + def initialize_sqlite_id_name_url_db + @db = SQLite3::Database.new 'id_name_url_map.db' @db.execute <<-SQL CREATE TABLE IF NOT EXISTS user_id_map ( old_user_id INTEGER PRIMARY KEY, @@ -42,6 +49,15 @@ class GossamerForumsImporter < ImportScripts::Base new_category_id INTEGER ); SQL + @db.execute <<-SQL + CREATE TABLE IF NOT EXISTS username_map ( + id INTEGER PRIMARY KEY, + old_username TEXT, + new_username TEXT, + email TEXT, + real_name TEXT + ); + SQL end def insert_user_id_mapping(old_user_id, new_user_id) @@ -60,41 +76,61 @@ class GossamerForumsImporter < ImportScripts::Base @db.get_first_value "SELECT new_category_id FROM category_id_map WHERE old_category_id = ?", old_category_id end + def insert_username_mapping(old_username, new_username, email, real_name) + @db.execute "INSERT INTO username_map (old_username, new_username, email, real_name) VALUES (?, ?, ?, ?)", old_username, new_username, email, real_name + end + + # Define a method to export the username mapping table to a CSV file + def export_username_mapping_to_csv(filename) + CSV.open(filename, 'wb') do |csv| + # Add headers + csv << ['Old Username', 'New Username', 'Email', 'Full Name'] + + # Fetch data from the database + @db.execute("SELECT old_username, new_username, email, real_name FROM username_map") do |row| + csv << row + end + end + end + + # Execute an SQL query on the Gossamer Forums database def execute_query(query) @mysql_client.query(query, as: :hash) end # Sanitize the username to meet Discourse's requirements - def sanitize_username(username, email, name) - original_username = username - sanitized = username.gsub(/[^a-zA-Z0-9._-]/, '_') - sanitized = "#{sanitized}." if sanitized.length < 2 # Allow two-character usernames - sanitized = sanitized[0, 20] if sanitized.length > 20 - original_sanitized = sanitized + def sanitize_username(original_username, email, real_name) +# original_username = username + sanitized_username = username.gsub(/[^a-zA-Z0-9._-]/, '_') + sanitized_username = "#{sanitized_username}." if sanitized_username.length < 2 # Allow two-character usernames + sanitized_username = sanitized_username[0, 20] if sanitized_username.length > 20 + firststep_sanitized = sanitized_username - existing_user = User.find_by(username: sanitized) + existing_user = User.find_by(username: sanitized_username) if existing_user if existing_user.email.downcase == email.downcase && existing_user.name == name - return sanitized + return sanitized_username else counter = 1 - while User.exists?(username: sanitized) - sanitized = "#{original_sanitized}_#{counter}" - sanitized = sanitized[0, 20] if sanitized.length > 20 + while User.exists?(username: sanitized_username) + sanitized_username = "#{firststep_sanitized}_#{counter}" + sanitized_username = sanitized_username[0, 20] if sanitized_username.length > 20 counter += 1 end end end - if original_username != sanitized - puts "Sanitized username: '#{original_username}' --> '#{sanitized}'" + if original_username != sanitized_username + # The Discourse username is not the same as the Gossamer Forums username + puts "Sanitized username: '#{original_username}' --> '#{sanitized_username}'" + insert_username_mapping(original_username, sanitized_username, email, real_name) # else -# puts "UNsanitized username: '#{original_username}' --> '#{sanitized}'" +# puts "UNsanitized username: '#{original_username}' --> '#{sanitized_username}'" end - sanitized + sanitized_username end @@ -214,14 +250,14 @@ end end # For each user, add user ID mapping to SQLite now that we know what the Discourse user ID is, ... and append user bio and import user files - users.each do |user| - discourse_username = sanitize_username(user[:username], user[:email], user[:name]) - discourse_user = User.find_by(username: discourse_username) + users.each do |discourse_user| + # discourse_username = sanitize_username(user[:username], user[:email], user[:name]) + # discourse_user = User.find_by(username: discourse_username) - if discourse_user.nil? - puts "User #{user[:username]} --> #{discourse_username} not found in Discourse. Skipping file import." - next - end + # if discourse_user.nil? + # puts "User #{user[:username]} --> #{discourse_username} not found in Discourse. Skipping file import." + # next + # end # # Store the user ID mapping # @user_id_map[user[:id]] = discourse_user.id @@ -556,6 +592,7 @@ end RateLimiter.disable puts "Starting Gossamer Forums import..." # import_users + # export_username_mapping_to_csv # import_categories # import_topics_and_posts import_personal_messages