diff --git a/Catalogger.Backend/Api/GuildsController.Remove.cs b/Catalogger.Backend/Api/GuildsController.Remove.cs index 1490884..08f0d61 100644 --- a/Catalogger.Backend/Api/GuildsController.Remove.cs +++ b/Catalogger.Backend/Api/GuildsController.Remove.cs @@ -19,6 +19,7 @@ using Catalogger.Backend.Bot; using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; +using Dapper; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Remora.Discord.Extensions.Embeds; @@ -40,7 +41,7 @@ public partial class GuildsController ); } - var guildConfig = await db.GetGuildAsync(guildId.Value, false); + var guildConfig = await guildRepository.GetAsync(guildId); var logChannelId = webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildUpdate) ?? webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildMemberRemove); @@ -80,17 +81,32 @@ public partial class GuildsController ); } - await using var tx = await db.Database.BeginTransactionAsync(); - var inviteCount = await db - .Invites.Where(i => i.GuildId == guildId.Value) - .ExecuteDeleteAsync(); - var watchlistCount = await db - .Watchlists.Where(w => w.GuildId == guildId.Value) - .ExecuteDeleteAsync(); - var messageCount = await db - .Messages.Where(m => m.GuildId == guildId.Value) - .ExecuteDeleteAsync(); - await db.Guilds.Where(g => g.Id == guildId.Value).ExecuteDeleteAsync(); + await using var tx = await dbConn.BeginTransactionAsync(); + + var inviteCount = await dbConn.ExecuteAsync( + "delete from invites where guild_id = @GuildId", + new { GuildId = guildId.Value }, + tx + ); + + var watchlistCount = await dbConn.ExecuteAsync( + "delete from watchlists where guild_id = @GuildId", + new { GuildId = guildId.Value }, + tx + ); + + var messageCount = await dbConn.ExecuteAsync( + "delete from messages where guild_id = @GuildId", + new { GuildId = guildId.Value }, + tx + ); + + await dbConn.ExecuteAsync( + "delete from guilds where id = @GuildId", + new { GuildId = guildId.Value }, + tx + ); + await tx.CommitAsync(); _logger.Information( diff --git a/Catalogger.Backend/Api/GuildsController.cs b/Catalogger.Backend/Api/GuildsController.cs index b21176b..6517ae2 100644 --- a/Catalogger.Backend/Api/GuildsController.cs +++ b/Catalogger.Backend/Api/GuildsController.cs @@ -18,8 +18,8 @@ using Catalogger.Backend.Api.Middleware; using Catalogger.Backend.Cache; using Catalogger.Backend.Cache.InMemoryCache; using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Queries; -using Catalogger.Backend.Database.Redis; +using Catalogger.Backend.Database.Dapper; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Services; using Microsoft.AspNetCore.Mvc; using Remora.Discord.API; @@ -33,6 +33,8 @@ namespace Catalogger.Backend.Api; public partial class GuildsController( ILogger logger, DatabaseContext db, + DatabaseConnection dbConn, + GuildRepository guildRepository, GuildCache guildCache, EmojiCache emojiCache, ChannelCache channelCache, @@ -70,7 +72,7 @@ public partial class GuildsController( { var (guildId, guild) = await ParseGuildAsync(id); - var guildConfig = await db.GetGuildAsync(guildId.Value, false); + var guildConfig = await guildRepository.GetAsync(guildId); var channels = channelCache .GuildChannels(guildId) @@ -134,12 +136,12 @@ public partial class GuildsController( [ProducesResponseType(statusCode: StatusCodes.Status200OK)] public async Task PatchGuildAsync(string id, [FromBody] ChannelRequest req) { - var (guildId, guild) = await ParseGuildAsync(id); + var (guildId, _) = await ParseGuildAsync(id); var guildChannels = channelCache .GuildChannels(guildId) .Where(c => c.Type is ChannelType.GuildText) .ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); if (req.IgnoredChannels != null) { @@ -316,9 +318,7 @@ public partial class GuildsController( ) guildConfig.Channels.MessageDeleteBulk = req.MessageDeleteBulk ?? 0; - db.Update(guildConfig); - await db.SaveChangesAsync(); - + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); return Ok(guildConfig.Channels); } diff --git a/Catalogger.Backend/Bot/Commands/ChannelCommands.cs b/Catalogger.Backend/Bot/Commands/ChannelCommands.cs index e11178c..438459a 100644 --- a/Catalogger.Backend/Bot/Commands/ChannelCommands.cs +++ b/Catalogger.Backend/Bot/Commands/ChannelCommands.cs @@ -17,6 +17,7 @@ using System.ComponentModel; using Catalogger.Backend.Cache; using Catalogger.Backend.Cache.InMemoryCache; using Catalogger.Backend.Database; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; @@ -42,7 +43,7 @@ namespace Catalogger.Backend.Bot.Commands; public class ChannelCommands( ILogger logger, Config config, - DatabaseContext db, + GuildRepository guildRepository, GuildCache guildCache, ChannelCache channelCache, IMemberCache memberCache, @@ -207,7 +208,7 @@ public class ChannelCommands( if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild not in cache"); var guildChannels = channelCache.GuildChannels(guildId).ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var (embeds, components) = BuildRootMenu(guildChannels, guild, guildConfig); diff --git a/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs b/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs index c96dd36..38bfc71 100644 --- a/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs +++ b/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs @@ -14,8 +14,7 @@ // along with this program. If not, see . using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Queries; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Remora.Discord.API.Abstractions.Objects; @@ -24,7 +23,6 @@ using Remora.Discord.API.Objects; using Remora.Discord.Commands.Attributes; using Remora.Discord.Commands.Contexts; using Remora.Discord.Commands.Extensions; -using Remora.Discord.Commands.Feedback.Messages; using Remora.Discord.Commands.Feedback.Services; using Remora.Discord.Commands.Services; using Remora.Discord.Interactivity; @@ -36,7 +34,7 @@ namespace Catalogger.Backend.Bot.Commands; public class ChannelCommandsComponents( ILogger logger, - DatabaseContext db, + GuildRepository guildRepository, GuildCache guildCache, ChannelCache channelCache, ContextInjectionService contextInjection, @@ -62,7 +60,7 @@ public class ChannelCommandsComponents( if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild not in cache"); var guildChannels = channelCache.GuildChannels(guildId).ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var result = await dataService.LeaseDataAsync(msg.ID); await using var lease = result.GetOrThrow(); @@ -166,8 +164,7 @@ public class ChannelCommandsComponents( throw new ArgumentOutOfRangeException(); } - db.Update(guildConfig); - await db.SaveChangesAsync(); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); goto case "return"; case "return": var (e, c) = ChannelCommands.BuildRootMenu(guildChannels, guild, guildConfig); @@ -260,7 +257,7 @@ public class ChannelCommandsComponents( throw new CataloggerError("No guild ID in context"); if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild not in cache"); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var channelId = channels[0].ID.ToUlong(); var result = await dataService.LeaseDataAsync(msg.ID); @@ -354,8 +351,7 @@ public class ChannelCommandsComponents( throw new ArgumentOutOfRangeException(); } - db.Update(guildConfig); - await db.SaveChangesAsync(); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); List embeds = [ diff --git a/Catalogger.Backend/Bot/Commands/IgnoreChannelCommands.cs b/Catalogger.Backend/Bot/Commands/IgnoreChannelCommands.cs index a60ceb3..afa9165 100644 --- a/Catalogger.Backend/Bot/Commands/IgnoreChannelCommands.cs +++ b/Catalogger.Backend/Bot/Commands/IgnoreChannelCommands.cs @@ -16,8 +16,7 @@ using System.ComponentModel; using Catalogger.Backend.Cache; using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Queries; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Remora.Commands.Attributes; @@ -38,7 +37,7 @@ namespace Catalogger.Backend.Bot.Commands; [DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)] public class IgnoreChannelCommands( ILogger logger, - DatabaseContext db, + GuildRepository guildRepository, IMemberCache memberCache, GuildCache guildCache, ChannelCache channelCache, @@ -66,7 +65,7 @@ public class IgnoreChannelCommands( ) { var (_, guildId) = contextInjection.GetUserAndGuild(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); if (guildConfig.Channels.IgnoredChannels.Contains(channel.ID.Value)) return await feedbackService.ReplyAsync( @@ -75,8 +74,7 @@ public class IgnoreChannelCommands( ); guildConfig.Channels.IgnoredChannels.Add(channel.ID.Value); - db.Update(guildConfig); - await db.SaveChangesAsync(); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); return await feedbackService.ReplyAsync( $"Successfully added {(channel.Type == ChannelType.GuildCategory ? channel.Name : $"<#{channel.ID}>")} to the list of ignored channels." @@ -90,7 +88,7 @@ public class IgnoreChannelCommands( ) { var (_, guildId) = contextInjection.GetUserAndGuild(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); if (!guildConfig.Channels.IgnoredChannels.Contains(channel.ID.Value)) return await feedbackService.ReplyAsync( @@ -99,8 +97,7 @@ public class IgnoreChannelCommands( ); guildConfig.Channels.IgnoredChannels.Remove(channel.ID.Value); - db.Update(guildConfig); - await db.SaveChangesAsync(); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); return await feedbackService.ReplyAsync( $"Successfully removed {(channel.Type == ChannelType.GuildCategory ? channel.Name : $"<#{channel.ID}>")} from the list of ignored channels." @@ -116,7 +113,7 @@ public class IgnoreChannelCommands( throw new CataloggerError("Guild not in cache"); var guildChannels = channelCache.GuildChannels(guildId).ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var member = await memberCache.TryGetAsync(guildId, userId); if (member == null) diff --git a/Catalogger.Backend/Bot/Commands/KeyRoleCommands.cs b/Catalogger.Backend/Bot/Commands/KeyRoleCommands.cs index 977e016..94a1bcd 100644 --- a/Catalogger.Backend/Bot/Commands/KeyRoleCommands.cs +++ b/Catalogger.Backend/Bot/Commands/KeyRoleCommands.cs @@ -15,8 +15,7 @@ using System.ComponentModel; using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Queries; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Extensions; using Remora.Commands.Attributes; using Remora.Commands.Groups; @@ -33,7 +32,7 @@ namespace Catalogger.Backend.Bot.Commands; [Group("key-roles")] [DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)] public class KeyRoleCommands( - DatabaseContext db, + GuildRepository guildRepository, ContextInjectionService contextInjection, IFeedbackService feedbackService, GuildCache guildCache, @@ -48,7 +47,7 @@ public class KeyRoleCommands( if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild not in cache"); var guildRoles = roleCache.GuildRoles(guildId).ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); if (guildConfig.KeyRoles.Length == 0) return await feedbackService.ReplyAsync( @@ -85,17 +84,14 @@ public class KeyRoleCommands( if (role == null) throw new CataloggerError("Role is not cached"); - var guildConfig = await db.GetGuildAsync(guildId); - if (guildConfig.KeyRoles.Any(id => role.ID == id)) + var guildConfig = await guildRepository.GetAsync(guildId); + if (guildConfig.KeyRoles.Any(id => role.ID.Value == id)) return await feedbackService.ReplyAsync( $"{role.Name} is already a key role.", isEphemeral: true ); - guildConfig.KeyRoles = guildConfig.KeyRoles.Append(role.ID.Value).ToArray(); - db.Update(guildConfig); - await db.SaveChangesAsync(); - + await guildRepository.AddKeyRoleAsync(guildId, role.ID); return await feedbackService.ReplyAsync($"Added {role.Name} to this server's key roles!"); } @@ -110,17 +106,14 @@ public class KeyRoleCommands( if (role == null) throw new CataloggerError("Role is not cached"); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); if (guildConfig.KeyRoles.All(id => role.ID != id)) return await feedbackService.ReplyAsync( $"{role.Name} is already not a key role.", isEphemeral: true ); - guildConfig.KeyRoles = guildConfig.KeyRoles.Except([role.ID.Value]).ToArray(); - db.Update(guildConfig); - await db.SaveChangesAsync(); - + await guildRepository.RemoveKeyRoleAsync(guildId, role.ID); return await feedbackService.ReplyAsync( $"Removed {role.Name} from this server's key roles!" ); diff --git a/Catalogger.Backend/Bot/Commands/RedirectCommands.cs b/Catalogger.Backend/Bot/Commands/RedirectCommands.cs index d5418d0..86e272f 100644 --- a/Catalogger.Backend/Bot/Commands/RedirectCommands.cs +++ b/Catalogger.Backend/Bot/Commands/RedirectCommands.cs @@ -15,8 +15,7 @@ using System.ComponentModel; using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Queries; +using Catalogger.Backend.Database.Dapper.Repositories; using Catalogger.Backend.Extensions; using Remora.Commands.Attributes; using Remora.Commands.Groups; @@ -34,7 +33,7 @@ namespace Catalogger.Backend.Bot.Commands; [Description("Commands for configuring log redirects.")] [DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)] public class RedirectCommands( - DatabaseContext db, + GuildRepository guildRepository, GuildCache guildCache, ChannelCache channelCache, ContextInjectionService contextInjectionService, @@ -60,10 +59,9 @@ public class RedirectCommands( ) { var (_, guildId) = contextInjectionService.GetUserAndGuild(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); guildConfig.Channels.Redirects[source.ID.Value] = target.ID.Value; - db.Update(guildConfig); - await db.SaveChangesAsync(); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); var output = $"Success! Edited and deleted messages from {FormatChannel(source)} will now be redirected to <#{target.ID}>."; @@ -100,9 +98,11 @@ public class RedirectCommands( ) { var (_, guildId) = contextInjectionService.GetUserAndGuild(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var wasSet = guildConfig.Channels.Redirects.Remove(source.ID.Value); + await guildRepository.UpdateChannelConfigAsync(guildId, guildConfig.Channels); + var output = wasSet ? $"Removed the redirect for {FormatChannel(source)}! Message logs from" + $"{(source.Type == ChannelType.GuildCategory ? "that category's channels" : "that channel")}" @@ -132,9 +132,6 @@ public class RedirectCommands( $"\nHowever, all channels in the {parentChannelName} category are being redirected to <#{parentRedirect}>."; } - db.Update(guildConfig); - await db.SaveChangesAsync(); - return await feedbackService.ReplyAsync(output); } @@ -146,7 +143,7 @@ public class RedirectCommands( if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild was not cached"); var guildChannels = channelCache.GuildChannels(guildId).ToList(); - var guildConfig = await db.GetGuildAsync(guildId); + var guildConfig = await guildRepository.GetAsync(guildId); var fields = new List(); diff --git a/Catalogger.Backend/Bot/Responders/Invites/InviteDeleteResponder.cs b/Catalogger.Backend/Bot/Responders/Invites/InviteDeleteResponder.cs index c0a2896..b33ad94 100644 --- a/Catalogger.Backend/Bot/Responders/Invites/InviteDeleteResponder.cs +++ b/Catalogger.Backend/Bot/Responders/Invites/InviteDeleteResponder.cs @@ -14,13 +14,9 @@ // along with this program. If not, see . using Catalogger.Backend.Cache; -using Catalogger.Backend.Database; -using Catalogger.Backend.Database.Dapper; using Catalogger.Backend.Database.Dapper.Repositories; -using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; -using Microsoft.EntityFrameworkCore; using Remora.Discord.API.Abstractions.Gateway.Events; using Remora.Discord.API.Abstractions.Rest; using Remora.Discord.Extensions.Embeds; diff --git a/Catalogger.Backend/Bot/Responders/Members/GuildMemberAddResponder.cs b/Catalogger.Backend/Bot/Responders/Members/GuildMemberAddResponder.cs index 6460717..dfb56f5 100644 --- a/Catalogger.Backend/Bot/Responders/Members/GuildMemberAddResponder.cs +++ b/Catalogger.Backend/Bot/Responders/Members/GuildMemberAddResponder.cs @@ -15,13 +15,10 @@ using Catalogger.Backend.Cache; using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; using Catalogger.Backend.Database.Dapper.Repositories; -using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Humanizer; -using Microsoft.EntityFrameworkCore; using Remora.Discord.API; using Remora.Discord.API.Abstractions.Gateway.Events; using Remora.Discord.API.Abstractions.Objects; @@ -35,9 +32,9 @@ namespace Catalogger.Backend.Bot.Responders.Members; public class GuildMemberAddResponder( ILogger logger, - DatabaseContext db, InviteRepository inviteRepository, GuildRepository guildRepository, + WatchlistRepository watchlistRepository, IMemberCache memberCache, IInviteCache inviteCache, UserCache userCache, @@ -159,7 +156,7 @@ public class GuildMemberAddResponder( ); } - var watchlist = await db.GetWatchlistEntryAsync(member.GuildID, user.ID, ct); + var watchlist = await watchlistRepository.GetWatchlistEntryAsync(member.GuildID, user.ID); if (watchlist != null) { var moderator = await userCache.GetUserAsync( diff --git a/Catalogger.Backend/Bot/Responders/Messages/MessageUpdateResponder.cs b/Catalogger.Backend/Bot/Responders/Messages/MessageUpdateResponder.cs index 641fabd..f9c0489 100644 --- a/Catalogger.Backend/Bot/Responders/Messages/MessageUpdateResponder.cs +++ b/Catalogger.Backend/Bot/Responders/Messages/MessageUpdateResponder.cs @@ -14,9 +14,7 @@ // along with this program. If not, see . using Catalogger.Backend.Cache.InMemoryCache; -using Catalogger.Backend.Database; using Catalogger.Backend.Database.Dapper.Repositories; -using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Remora.Discord.API; @@ -32,7 +30,7 @@ namespace Catalogger.Backend.Bot.Responders.Messages; public class MessageUpdateResponder( ILogger logger, - DatabaseContext db, + GuildRepository guildRepository, ChannelCache channelCache, UserCache userCache, MessageRepository messageRepository, @@ -57,7 +55,7 @@ public class MessageUpdateResponder( return Result.Success; } - var guildConfig = await db.GetGuildAsync(msg.GuildID.Value, false, ct); + var guildConfig = await guildRepository.GetAsync(msg.GuildID); if (await messageRepository.IsMessageIgnoredAsync(msg.ID.Value)) { diff --git a/Catalogger.Backend/Database/Dapper/DatabaseConnection.cs b/Catalogger.Backend/Database/Dapper/DatabaseConnection.cs index 997aab5..ed6bafe 100644 --- a/Catalogger.Backend/Database/Dapper/DatabaseConnection.cs +++ b/Catalogger.Backend/Database/Dapper/DatabaseConnection.cs @@ -43,7 +43,7 @@ public class DatabaseConnection(Guid id, ILogger logger, NpgsqlConnection inner) DatabasePool.DecrementConnections(); var openFor = DateTimeOffset.UtcNow - _openTime; - _logger.Debug("Closing connection {ConnId}, open for {OpenFor}", ConnectionId, openFor); + _logger.Verbose("Closing connection {ConnId}, open for {OpenFor}", ConnectionId, openFor); _hasClosed = true; await inner.CloseAsync(); } @@ -53,7 +53,7 @@ public class DatabaseConnection(Guid id, ILogger logger, NpgsqlConnection inner) CancellationToken cancellationToken ) { - _logger.Debug("Beginning transaction on connection {ConnId}", ConnectionId); + _logger.Verbose("Beginning transaction on connection {ConnId}", ConnectionId); return await inner.BeginTransactionAsync(isolationLevel, cancellationToken); } diff --git a/Catalogger.Backend/Database/Dapper/DatabasePool.cs b/Catalogger.Backend/Database/Dapper/DatabasePool.cs index 98296f1..3d1342f 100644 --- a/Catalogger.Backend/Database/Dapper/DatabasePool.cs +++ b/Catalogger.Backend/Database/Dapper/DatabasePool.cs @@ -67,7 +67,7 @@ public class DatabasePool private Guid LogOpen() { var connId = Guid.NewGuid(); - _logger.Debug("Opening database connection {ConnId}", connId); + _logger.Verbose("Opening database connection {ConnId}", connId); IncrementConnections(); return connId; } diff --git a/Catalogger.Backend/Database/Dapper/Repositories/GuildRepository.cs b/Catalogger.Backend/Database/Dapper/Repositories/GuildRepository.cs index 5a1b664..44d39b3 100644 --- a/Catalogger.Backend/Database/Dapper/Repositories/GuildRepository.cs +++ b/Catalogger.Backend/Database/Dapper/Repositories/GuildRepository.cs @@ -75,6 +75,24 @@ public class GuildRepository(ILogger logger, DatabaseConnection conn) } ); + public async Task AddKeyRoleAsync(Snowflake guildId, Snowflake roleId) => + await conn.ExecuteAsync( + "update guilds set key_roles = array_append(key_roles, @RoleId) where id = @GuildId", + new { GuildId = guildId.Value, RoleId = roleId.Value } + ); + + public async Task RemoveKeyRoleAsync(Snowflake guildId, Snowflake roleId) => + await conn.ExecuteAsync( + "update guilds set key_roles = array_remove(key_roles, @RoleId) where id = @GuildId", + new { GuildId = guildId.Value, RoleId = roleId.Value } + ); + + public async Task UpdateChannelConfigAsync(Snowflake id, Guild.ChannelConfig config) => + await conn.ExecuteAsync( + "update guilds set channels = @Channels where id = @Id", + new { Id = id, Channels = config } + ); + public void Dispose() { conn.Dispose(); diff --git a/Catalogger.Backend/Database/Dapper/Repositories/WatchlistRepository.cs b/Catalogger.Backend/Database/Dapper/Repositories/WatchlistRepository.cs new file mode 100644 index 0000000..0f06ab8 --- /dev/null +++ b/Catalogger.Backend/Database/Dapper/Repositories/WatchlistRepository.cs @@ -0,0 +1,53 @@ +// 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 Catalogger.Backend.Database.Models; +using Dapper; +using Remora.Rest.Core; + +namespace Catalogger.Backend.Database.Dapper.Repositories; + +public class WatchlistRepository(ILogger logger, DatabaseConnection conn) + : IDisposable, + IAsyncDisposable +{ + private readonly ILogger _logger = logger.ForContext(); + + public async Task> GetGuildWatchlistAsync(Snowflake guildId) => + ( + await conn.QueryAsync( + "select * from watchlists where guild_id = @GuildId", + new { GuildId = guildId.Value } + ) + ).ToList(); + + public async Task GetWatchlistEntryAsync(Snowflake guildId, Snowflake userId) => + await conn.QueryFirstOrDefaultAsync( + "select * from watchlists where guild_id = @GuildId and user_id = @UserId", + new { GuildId = guildId.Value, UserId = userId.Value } + ); + + public void Dispose() + { + conn.Dispose(); + GC.SuppressFinalize(this); + } + + public async ValueTask DisposeAsync() + { + await conn.DisposeAsync(); + GC.SuppressFinalize(this); + } +} diff --git a/Catalogger.Backend/Database/Queries/QueryExtensions.cs b/Catalogger.Backend/Database/Queries/QueryExtensions.cs index 128a184..457f961 100644 --- a/Catalogger.Backend/Database/Queries/QueryExtensions.cs +++ b/Catalogger.Backend/Database/Queries/QueryExtensions.cs @@ -53,14 +53,4 @@ public static class QueryExtensions throw new CataloggerError("Guild not found, was not initialized during guild create"); return guild; } - - public static async Task GetWatchlistEntryAsync( - this DatabaseContext db, - Snowflake guildId, - Snowflake userId, - CancellationToken ct = default - ) => - await db - .Watchlists.AsNoTracking() - .FirstOrDefaultAsync(w => w.GuildId == guildId.Value && w.UserId == userId.Value, ct); } diff --git a/Catalogger.Backend/Extensions/StartupExtensions.cs b/Catalogger.Backend/Extensions/StartupExtensions.cs index a921874..32a8ca3 100644 --- a/Catalogger.Backend/Extensions/StartupExtensions.cs +++ b/Catalogger.Backend/Extensions/StartupExtensions.cs @@ -109,6 +109,7 @@ public static class StartupExtensions .AddScoped() .AddScoped() .AddScoped() + .AddScoped() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/Catalogger.Backend/Services/MetricsCollectionService.cs b/Catalogger.Backend/Services/MetricsCollectionService.cs index 40c9c0c..cb0ec64 100644 --- a/Catalogger.Backend/Services/MetricsCollectionService.cs +++ b/Catalogger.Backend/Services/MetricsCollectionService.cs @@ -16,6 +16,8 @@ using System.Diagnostics; using Catalogger.Backend.Cache.InMemoryCache; using Catalogger.Backend.Database; +using Catalogger.Backend.Database.Dapper; +using Dapper; using Humanizer; using Microsoft.EntityFrameworkCore; using Prometheus; @@ -39,8 +41,9 @@ public class MetricsCollectionService( await using var scope = services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService(); + await using var conn = scope.ServiceProvider.GetRequiredService(); - var messageCount = await db.Messages.CountAsync(ct); + var messageCount = await conn.ExecuteScalarAsync("select count(id) from messages"); CataloggerMetrics.GuildsCached.Set(guildCache.Size); CataloggerMetrics.ChannelsCached.Set(channelCache.Size); diff --git a/Catalogger.Backend/Services/WebhookExecutorService.cs b/Catalogger.Backend/Services/WebhookExecutorService.cs index f733158..eed437e 100644 --- a/Catalogger.Backend/Services/WebhookExecutorService.cs +++ b/Catalogger.Backend/Services/WebhookExecutorService.cs @@ -61,6 +61,7 @@ public class WebhookExecutorService( public void QueueLog(Guild guildConfig, LogChannelType logChannelType, IEmbed embed) { var logChannel = GetLogChannel(guildConfig, logChannelType, channelId: null, userId: null); + _logger.Debug("Channel to log {Type} to: {LogChannel}", logChannelType, logChannel); if (logChannel == null) return; @@ -72,6 +73,7 @@ public class WebhookExecutorService( /// public void QueueLog(ulong channelId, IEmbed embed) { + _logger.Debug("Channel to log to: {LogChannel}", channelId); if (channelId == 0) return; diff --git a/Catalogger.GoImporter/GuildImport.cs b/Catalogger.GoImporter/GuildImport.cs index 40a88d4..3238fdd 100644 --- a/Catalogger.GoImporter/GuildImport.cs +++ b/Catalogger.GoImporter/GuildImport.cs @@ -93,8 +93,8 @@ public static class GuildImport var dbGuild = new Guild { Id = guild.Id, - BannedSystems = guild.BannedSystems.ToList(), - KeyRoles = guild.KeyRoles.ToList(), + BannedSystems = guild.BannedSystems, + KeyRoles = guild.KeyRoles, Channels = channels, };