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:
sam 2024-11-05 22:22:12 +01:00
parent f0fcfd7bd3
commit e6d68338db
Signed by: sam
GPG key ID: 5F3C3C1B3166639D
7 changed files with 249 additions and 1 deletions

View file

@ -15,9 +15,11 @@
using Catalogger.Backend.Cache;
using Catalogger.Backend.Cache.InMemoryCache;
using Catalogger.Backend.Database.Models;
using Catalogger.Backend.Database.Repositories;
using Catalogger.Backend.Extensions;
using Catalogger.Backend.Services;
using NodaTime.Extensions;
using Remora.Discord.API.Abstractions.Gateway.Events;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.Extensions.Embeds;
@ -30,6 +32,8 @@ namespace Catalogger.Backend.Bot.Responders.Members;
public class GuildMemberUpdateResponder(
ILogger logger,
GuildRepository guildRepository,
TimeoutRepository timeoutRepository,
TimeoutService timeoutService,
UserCache userCache,
RoleCache roleCache,
IMemberCache memberCache,
@ -245,11 +249,15 @@ public class GuildMemberUpdateResponder(
var moderator = await userCache.TryFormatUserAsync(actionData.ModeratorId);
embed.AddField("Responsible moderator", moderator);
embed.AddField("Reason", actionData.Reason ?? "No reason given");
await UpdateTimeoutDatabaseAsync(member, actionData.ModeratorId);
}
else
{
embed.AddField("Responsible moderator", "*(unknown)*");
embed.AddField("Reason", "*(unknown)*");
await UpdateTimeoutDatabaseAsync(member, null);
}
var guildConfig = await guildRepository.GetAsync(member.GuildID);
@ -261,6 +269,27 @@ public class GuildMemberUpdateResponder(
return Result.Success;
}
private async Task UpdateTimeoutDatabaseAsync(IGuildMemberUpdate member, Snowflake? moderatorId)
{
var until = member.CommunicationDisabledUntil.OrDefault();
if (until == null)
{
// timeout was ended early, delete database entry
var oldTimeout = await timeoutRepository.RemoveAsync(member.GuildID, member.User.ID);
if (oldTimeout != null)
timeoutService.RemoveTimer(oldTimeout.Id);
return;
}
var dbTimeout = await timeoutRepository.SetAsync(
member.GuildID,
member.User.ID,
until.Value.ToInstant(),
moderatorId
);
timeoutService.AddTimer(dbTimeout);
}
private async Task<Result> HandleRoleUpdateAsync(
IGuildMemberUpdate member,
IReadOnlyList<Snowflake> oldRoles,