feat: store timeouts in database and log them ending
we have to do this because discord doesn't notify us when a timeout ends naturally, only when a moderator removes it early.
This commit is contained in:
parent
f0fcfd7bd3
commit
e6d68338db
7 changed files with 249 additions and 1 deletions
|
|
@ -0,0 +1 @@
|
|||
drop table timeouts;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
create table timeouts (
|
||||
id integer generated by default as identity primary key,
|
||||
user_id bigint not null,
|
||||
guild_id bigint not null,
|
||||
moderator_id bigint,
|
||||
until timestamptz not null
|
||||
);
|
||||
|
||||
create unique index ix_timeouts_user_guild on timeouts (user_id, guild_id);
|
||||
12
Catalogger.Backend/Database/Models/DiscordTimeout.cs
Normal file
12
Catalogger.Backend/Database/Models/DiscordTimeout.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using NodaTime;
|
||||
|
||||
namespace Catalogger.Backend.Database.Models;
|
||||
|
||||
public class DiscordTimeout
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public ulong UserId { get; init; }
|
||||
public ulong GuildId { get; init; }
|
||||
public ulong? ModeratorId { get; init; }
|
||||
public Instant Until { get; init; }
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
using Catalogger.Backend.Database.Models;
|
||||
using Dapper;
|
||||
using NodaTime;
|
||||
using Remora.Rest.Core;
|
||||
|
||||
namespace Catalogger.Backend.Database.Repositories;
|
||||
|
||||
public class TimeoutRepository(DatabaseConnection conn) : IDisposable, IAsyncDisposable
|
||||
{
|
||||
public async Task<DiscordTimeout?> GetAsync(int id) =>
|
||||
await conn.QueryFirstOrDefaultAsync<DiscordTimeout>(
|
||||
"select * from timeouts where id = @id",
|
||||
new { id }
|
||||
);
|
||||
|
||||
public async Task<DiscordTimeout?> GetAsync(Snowflake guildId, Snowflake userId) =>
|
||||
await conn.QueryFirstOrDefaultAsync<DiscordTimeout>(
|
||||
"select * from timeouts where guild_id = @GuildId and user_id = @UserId",
|
||||
new { GuildId = guildId.Value, UserId = userId.Value }
|
||||
);
|
||||
|
||||
public async Task<List<DiscordTimeout>> GetAllAsync() =>
|
||||
(await conn.QueryAsync<DiscordTimeout>("select * from timeouts order by id")).ToList();
|
||||
|
||||
public async Task<DiscordTimeout> SetAsync(
|
||||
Snowflake guildId,
|
||||
Snowflake userId,
|
||||
Instant until,
|
||||
Snowflake? moderatorId
|
||||
) =>
|
||||
await conn.QueryFirstAsync<DiscordTimeout>(
|
||||
"""
|
||||
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<DiscordTimeout?> RemoveAsync(int id) =>
|
||||
await conn.QueryFirstOrDefaultAsync<DiscordTimeout>(
|
||||
"delete from timeouts where id = @id returning *",
|
||||
new { id }
|
||||
);
|
||||
|
||||
public async Task<DiscordTimeout?> RemoveAsync(Snowflake guildId, Snowflake userId) =>
|
||||
await conn.QueryFirstOrDefaultAsync<DiscordTimeout>(
|
||||
"delete from timeouts where guild_id = @GuildId and user_id = @UserId returning *",
|
||||
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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue