// Copyright (C) 2021-present sam (starshines.gay) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using System.Data.Common; using System.Diagnostics; using System.Text.Json; using Catalogger.Backend.Database; using Catalogger.Backend.Database.Models; using Dapper; using NodaTime.Extensions; using Serilog; namespace Catalogger.GoImporter; public static class GuildImport { public static async Task DoImportAsync(DatabaseConnection conn, string filename) { var rawData = await File.OpenText(filename).ReadToEndAsync(); var data = JsonSerializer.Deserialize(rawData, Program.JsonOptions); if (data == null) { Log.Error("Guilds JSON dump was deserialized as null, aborting"); return; } var watch = new Stopwatch(); watch.Start(); await using var tx = await conn.BeginTransactionAsync(); foreach (var g in data.Guilds) await ImportGuildAsync(conn, tx, g); foreach (var i in data.Invites) await ImportInviteAsync(conn, tx, i); foreach (var w in data.Watchlist) await ImportWatchlistEntryAsync(conn, tx, w); await tx.CommitAsync(); Log.Information( "Imported guilds, invites, and watchlist entries in {Duration}", watch.Elapsed.ToDuration() ); } private static async Task ImportGuildAsync( DatabaseConnection conn, DbTransaction tx, GoGuild guild ) { var channels = new Guild.ChannelConfig { IgnoredChannels = guild.IgnoredChannels.ToList(), IgnoredUsers = guild.IgnoredUsers.ToList(), GuildUpdate = guild.Channels.TryParse("GUILD_UPDATE"), GuildEmojisUpdate = guild.Channels.TryParse("GUILD_EMOJIS_UPDATE"), GuildRoleCreate = guild.Channels.TryParse("GUILD_ROLE_CREATE"), GuildRoleUpdate = guild.Channels.TryParse("GUILD_ROLE_UPDATE"), GuildRoleDelete = guild.Channels.TryParse("GUILD_ROLE_DELETE"), ChannelCreate = guild.Channels.TryParse("CHANNEL_CREATE"), ChannelUpdate = guild.Channels.TryParse("CHANNEL_UPDATE"), ChannelDelete = guild.Channels.TryParse("CHANNEL_DELETE"), GuildMemberAdd = guild.Channels.TryParse("GUILD_MEMBER_ADD"), GuildMemberUpdate = guild.Channels.TryParse("GUILD_MEMBER_UPDATE"), GuildKeyRoleUpdate = guild.Channels.TryParse("GUILD_KEY_ROLE_UPDATE"), GuildMemberNickUpdate = guild.Channels.TryParse("GUILD_MEMBER_NICK_UPDATE"), GuildMemberAvatarUpdate = guild.Channels.TryParse("GUILD_MEMBER_NICK_UPDATE"), GuildMemberTimeout = guild.Channels.TryParse("GUILD_MEMBER_KICK"), GuildMemberRemove = guild.Channels.TryParse("GUILD_MEMBER_REMOVE"), GuildMemberKick = guild.Channels.TryParse("GUILD_MEMBER_KICK"), GuildBanAdd = guild.Channels.TryParse("GUILD_BAN_ADD"), GuildBanRemove = guild.Channels.TryParse("GUILD_BAN_REMOVE"), InviteCreate = guild.Channels.TryParse("INVITE_CREATE"), InviteDelete = guild.Channels.TryParse("INVITE_DELETE"), MessageUpdate = guild.Channels.TryParse("MESSAGE_UPDATE"), MessageDelete = guild.Channels.TryParse("MESSAGE_DELETE"), MessageDeleteBulk = guild.Channels.TryParse("MESSAGE_DELETE_BULK"), }; foreach (var (key, value) in guild.Redirects) if (ulong.TryParse(key, out var fromId) && ulong.TryParse(value, out var toId)) channels.Redirects[fromId] = toId; await conn.ExecuteAsync( """ insert into guilds (id, channels, banned_systems, key_roles) values (@Id, @Channels::jsonb, @BannedSystems, @KeyRoles) """, new { guild.Id, Channels = channels, guild.BannedSystems, guild.KeyRoles, }, tx ); } private static async Task ImportInviteAsync( DatabaseConnection conn, DbTransaction tx, GoInvite invite ) { await conn.ExecuteAsync( "insert into invites (code, guild_id, name) values (@Code, @GuildId, @Name)", new { invite.GuildId, invite.Code, invite.Name, }, tx ); } private static async Task ImportWatchlistEntryAsync( DatabaseConnection conn, DbTransaction tx, GoWatchlistEntry watchlistEntry ) { await conn.ExecuteAsync( """ insert into watchlists (guild_id, user_id, added_at, moderator_id, reason) values (@GuildId, @UserId, @AddedAt, @ModeratorId, @Reason) """, new { watchlistEntry.GuildId, watchlistEntry.UserId, watchlistEntry.AddedAt, watchlistEntry.ModeratorId, watchlistEntry.Reason, }, tx ); } private static ulong TryParse(this Dictionary dict, string key) => dict.TryGetValue(key, out var raw) && ulong.TryParse(raw, out var id) ? id : 0; }