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 '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