v0.10 Add support for SQLite DB and CSV file generation for mapping of old to new usernames

This commit is contained in:
David Sainty 2024-06-20 01:13:08 +10:00
parent 9903c42a5e
commit a6d48e825d

View File

@ -1,9 +1,16 @@
# gossamer threads migration-import code
# v0.10
require 'mysql2' require 'mysql2'
require 'open-uri' require 'open-uri'
require 'net/http' require 'net/http'
require 'tempfile' require 'tempfile'
require 'sqlite3' require 'sqlite3'
require 'digest'
require 'fileutils'
require 'csv'
require File.expand_path("../../../config/environment", __FILE__) require File.expand_path("../../../config/environment", __FILE__)
require_relative 'base' require_relative 'base'
@ -25,11 +32,11 @@ class GossamerForumsImporter < ImportScripts::Base
# # Create a mapping of old Gossamer user IDs to new Discourse user IDs # # Create a mapping of old Gossamer user IDs to new Discourse user IDs
# @user_id_map = {} # @user_id_map = {}
initialize_sqlite_user_id_db initialize_sqlite_id_name_url_db
end end
def initialize_sqlite_user_id_db def initialize_sqlite_id_name_url_db
@db = SQLite3::Database.new 'user_id_map.db' @db = SQLite3::Database.new 'id_name_url_map.db'
@db.execute <<-SQL @db.execute <<-SQL
CREATE TABLE IF NOT EXISTS user_id_map ( CREATE TABLE IF NOT EXISTS user_id_map (
old_user_id INTEGER PRIMARY KEY, old_user_id INTEGER PRIMARY KEY,
@ -42,6 +49,15 @@ class GossamerForumsImporter < ImportScripts::Base
new_category_id INTEGER new_category_id INTEGER
); );
SQL 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 end
def insert_user_id_mapping(old_user_id, new_user_id) 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 @db.get_first_value "SELECT new_category_id FROM category_id_map WHERE old_category_id = ?", old_category_id
end 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 # Execute an SQL query on the Gossamer Forums database
def execute_query(query) def execute_query(query)
@mysql_client.query(query, as: :hash) @mysql_client.query(query, as: :hash)
end end
# Sanitize the username to meet Discourse's requirements # Sanitize the username to meet Discourse's requirements
def sanitize_username(username, email, name) def sanitize_username(original_username, email, real_name)
original_username = username # original_username = username
sanitized = username.gsub(/[^a-zA-Z0-9._-]/, '_') sanitized_username = username.gsub(/[^a-zA-Z0-9._-]/, '_')
sanitized = "#{sanitized}." if sanitized.length < 2 # Allow two-character usernames sanitized_username = "#{sanitized_username}." if sanitized_username.length < 2 # Allow two-character usernames
sanitized = sanitized[0, 20] if sanitized.length > 20 sanitized_username = sanitized_username[0, 20] if sanitized_username.length > 20
original_sanitized = sanitized 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
if existing_user.email.downcase == email.downcase && existing_user.name == name if existing_user.email.downcase == email.downcase && existing_user.name == name
return sanitized return sanitized_username
else else
counter = 1 counter = 1
while User.exists?(username: sanitized) while User.exists?(username: sanitized_username)
sanitized = "#{original_sanitized}_#{counter}" sanitized_username = "#{firststep_sanitized}_#{counter}"
sanitized = sanitized[0, 20] if sanitized.length > 20 sanitized_username = sanitized_username[0, 20] if sanitized_username.length > 20
counter += 1 counter += 1
end end
end end
end end
if original_username != sanitized if original_username != sanitized_username
puts "Sanitized username: '#{original_username}' --> '#{sanitized}'" # 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 # else
# puts "UNsanitized username: '#{original_username}' --> '#{sanitized}'" # puts "UNsanitized username: '#{original_username}' --> '#{sanitized_username}'"
end end
sanitized sanitized_username
end end
@ -214,14 +250,14 @@ end
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 # 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| users.each do |discourse_user|
discourse_username = sanitize_username(user[:username], user[:email], user[:name]) # discourse_username = sanitize_username(user[:username], user[:email], user[:name])
discourse_user = User.find_by(username: discourse_username) # discourse_user = User.find_by(username: discourse_username)
if discourse_user.nil? # if discourse_user.nil?
puts "User #{user[:username]} --> #{discourse_username} not found in Discourse. Skipping file import." # puts "User #{user[:username]} --> #{discourse_username} not found in Discourse. Skipping file import."
next # next
end # end
# # Store the user ID mapping # # Store the user ID mapping
# @user_id_map[user[:id]] = discourse_user.id # @user_id_map[user[:id]] = discourse_user.id
@ -556,6 +592,7 @@ end
RateLimiter.disable RateLimiter.disable
puts "Starting Gossamer Forums import..." puts "Starting Gossamer Forums import..."
# import_users # import_users
# export_username_mapping_to_csv
# import_categories # import_categories
# import_topics_and_posts # import_topics_and_posts
import_personal_messages import_personal_messages