using Catalogger.Backend.Database.Models; using Dapper; using NodaTime; using Remora.Rest.Core; namespace Catalogger.Backend.Database.Repositories; public class TimeoutRepository(DatabaseConnection conn, IClock clock) : IDisposable, IAsyncDisposable { public async Task GetAsync(int id) => await conn.QueryFirstOrDefaultAsync( "select * from timeouts where id = @id", new { id } ); public async Task GetAsync(Snowflake guildId, Snowflake userId) => await conn.QueryFirstOrDefaultAsync( "select * from timeouts where guild_id = @GuildId and user_id = @UserId", new { GuildId = guildId.Value, UserId = userId.Value } ); public async Task> GetAllAsync() => ( await conn.QueryAsync( "select * from timeouts where until > now() order by id" ) ).ToList(); public async Task SetAsync( Snowflake guildId, Snowflake userId, Instant until, Snowflake? moderatorId ) => await conn.QueryFirstAsync( """ insert into timeouts (user_id, guild_id, moderator_id, until) values (@UserId, @GuildId, @ModeratorId, @Until) on conflict (user_id, guild_id) do update set moderator_id = @ModeratorId, until = @Until returning * """, new { UserId = userId.Value, GuildId = guildId.Value, ModeratorId = moderatorId?.Value, Until = until, } ); public async Task RemoveAsync(int id) => await conn.QueryFirstOrDefaultAsync( "delete from timeouts where id = @id returning *", new { id } ); public async Task RemoveAsync(Snowflake guildId, Snowflake userId) => await conn.QueryFirstOrDefaultAsync( "delete from timeouts where guild_id = @GuildId and user_id = @UserId returning *", new { GuildId = guildId.Value, UserId = userId.Value } ); public async Task RemoveExpiredTimeoutsAsync() => await conn.ExecuteAsync( "delete from timeouts where until < @Expiry", new { Expiry = clock.GetCurrentInstant() - Duration.FromMinutes(5) } ); public void Dispose() { conn.Dispose(); GC.SuppressFinalize(this); } public async ValueTask DisposeAsync() { await conn.DisposeAsync(); GC.SuppressFinalize(this); } }