Foxnouns.NET/migrators/NetImporter/ImportUser.cs
2024-10-02 00:16:20 +02:00

174 lines
No EOL
5.4 KiB
C#

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using NodaTime.Extensions;
using Serilog;
namespace NetImporter;
public static class Users
{
public static async Task ImportUsers(string filename)
{
await using var db = await NetImporter.GetContextAsync();
await db.Database.ExecuteSqlRawAsync("SELECT 1");
var stopwatch = new Stopwatch();
stopwatch.Start();
var users = NetImporter.ReadFromFile<ImportUser>(filename).Output.Select(ConvertUser).ToList();
db.AddRange(users);
await db.SaveChangesAsync();
stopwatch.Stop();
Log.Information("Imported {Count} users in {Duration}", users.Count, stopwatch.ElapsedDuration());
}
private static User ConvertUser(ImportUser oldUser)
{
var user = new User
{
Id = oldUser.Id,
Username = oldUser.Username,
DisplayName = oldUser.DisplayName,
Bio = oldUser.Bio,
MemberTitle = oldUser.MemberTitle,
LastActive = oldUser.LastActive.ToInstant(),
Avatar = oldUser.AvatarHash,
Links = oldUser.Links ?? [],
Role = oldUser.ParseRole(),
Deleted = oldUser.Deleted,
DeletedAt = oldUser.DeletedAt?.ToInstant(),
DeletedBy = null
};
if (oldUser is { DiscordId: not null, DiscordUsername: not null })
{
user.AuthMethods.Add(new AuthMethod
{
Id = SnowflakeGenerator.Instance.GenerateSnowflake(),
AuthType = AuthType.Discord,
RemoteId = oldUser.DiscordId,
RemoteUsername = oldUser.DiscordUsername
});
}
if (oldUser is { TumblrId: not null, TumblrUsername: not null })
{
user.AuthMethods.Add(new AuthMethod
{
Id = SnowflakeGenerator.Instance.GenerateSnowflake(),
AuthType = AuthType.Tumblr,
RemoteId = oldUser.TumblrId,
RemoteUsername = oldUser.TumblrUsername
});
}
if (oldUser is { GoogleId: not null, GoogleUsername: not null })
{
user.AuthMethods.Add(new AuthMethod
{
Id = SnowflakeGenerator.Instance.GenerateSnowflake(),
AuthType = AuthType.Google,
RemoteId = oldUser.GoogleId,
RemoteUsername = oldUser.GoogleUsername
});
}
// Convert all custom preference UUIDs to snowflakes
var prefMapping = new Dictionary<string, Snowflake>();
foreach (var (key, value) in oldUser.CustomPreferences)
{
var newKey = SnowflakeGenerator.Instance.GenerateSnowflake();
prefMapping[key] = newKey;
user.CustomPreferences[newKey] = value;
}
foreach (var name in oldUser.Names ?? [])
{
user.Names.Add(new FieldEntry
{
Value = name.Value,
Status = prefMapping.TryGetValue(name.Status, out var newStatus) ? newStatus.ToString() : name.Status,
});
}
foreach (var pronoun in oldUser.Pronouns ?? [])
{
user.Pronouns.Add(new Pronoun
{
Value = pronoun.Value,
DisplayText = pronoun.DisplayText,
Status = prefMapping.TryGetValue(pronoun.Status, out var newStatus)
? newStatus.ToString()
: pronoun.Status,
});
}
foreach (var field in oldUser.Fields ?? [])
{
var entries = field.Entries.Select(entry => new FieldEntry
{
Value = entry.Value,
Status = prefMapping.TryGetValue(entry.Status, out var newStatus)
? newStatus.ToString()
: entry.Status,
})
.ToList();
user.Fields.Add(new Field
{
Name = field.Name,
Entries = entries.ToArray()
});
}
Log.Debug("Converted user {UserId}", oldUser.Id);
return user;
}
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Local")]
private record ImportUser(
Snowflake Id,
string Sid,
string Username,
string? DisplayName,
string? Bio,
string? MemberTitle,
OffsetDateTime LastActive,
string? AvatarHash,
string[]? Links,
FieldEntry[]? Names,
Pronoun[]? Pronouns,
Field[]? Fields,
string? DiscordId,
string? DiscordUsername,
string? FediverseId,
string? FediverseUsername,
long? FediverseAppId,
string? TumblrId,
string? TumblrUsername,
string? GoogleId,
string? GoogleUsername,
bool MemberListHidden,
string? Timezone,
string Role,
bool Deleted,
OffsetDateTime? DeletedAt,
string? DeleteReason,
Dictionary<string, User.CustomPreference> CustomPreferences)
{
public UserRole ParseRole() => Role switch
{
"USER" => UserRole.User,
"MODERATOR" => UserRole.Moderator,
"ADMIN" => UserRole.Admin,
_ => UserRole.User
};
}
}