From 516ce3a6e9c81630125b8b478e2fa94b450656b2 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 2 Sep 2024 17:00:33 +0200 Subject: [PATCH] wip: guild member remove --- .../Responders/Guilds/AuditLogResponder.cs | 14 ++++++ .../Guilds/GuildMemberRemoveResponder.cs | 49 +++++++++++++++++++ Catalogger.Backend/Cache/IMemberCache.cs | 1 + .../Cache/InMemoryCache/AuditLogCache.cs | 21 ++++++++ .../InMemoryCache/InMemoryMemberCache.cs | 8 ++- .../Cache/RedisCache/RedisMemberCache.cs | 3 ++ 6 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 Catalogger.Backend/Bot/Responders/Guilds/AuditLogResponder.cs create mode 100644 Catalogger.Backend/Bot/Responders/Guilds/GuildMemberRemoveResponder.cs create mode 100644 Catalogger.Backend/Cache/InMemoryCache/AuditLogCache.cs diff --git a/Catalogger.Backend/Bot/Responders/Guilds/AuditLogResponder.cs b/Catalogger.Backend/Bot/Responders/Guilds/AuditLogResponder.cs new file mode 100644 index 0000000..98d5dbc --- /dev/null +++ b/Catalogger.Backend/Bot/Responders/Guilds/AuditLogResponder.cs @@ -0,0 +1,14 @@ +using Catalogger.Backend.Cache.InMemoryCache; +using Remora.Discord.API.Abstractions.Gateway.Events; +using Remora.Discord.Gateway.Responders; +using Remora.Results; + +namespace Catalogger.Backend.Bot.Responders.Guilds; + +public class AuditLogResponder(AuditLogCache auditLogCache) : IResponder +{ + public Task RespondAsync(IGuildAuditLogEntryCreate evt, CancellationToken ct = default) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Catalogger.Backend/Bot/Responders/Guilds/GuildMemberRemoveResponder.cs b/Catalogger.Backend/Bot/Responders/Guilds/GuildMemberRemoveResponder.cs new file mode 100644 index 0000000..898df85 --- /dev/null +++ b/Catalogger.Backend/Bot/Responders/Guilds/GuildMemberRemoveResponder.cs @@ -0,0 +1,49 @@ +using Catalogger.Backend.Cache; +using Catalogger.Backend.Cache.InMemoryCache; +using Catalogger.Backend.Database; +using Catalogger.Backend.Extensions; +using Catalogger.Backend.Services; +using Remora.Discord.API.Abstractions.Gateway.Events; +using Remora.Discord.API.Abstractions.Rest; +using Remora.Discord.Extensions.Embeds; +using Remora.Discord.Gateway.Responders; +using Remora.Results; + +namespace Catalogger.Backend.Bot.Responders.Guilds; + +public class GuildMemberRemoveResponder( + ILogger logger, + DatabaseContext db, + IMemberCache memberCache, + UserCache userCache, + WebhookExecutorService webhookExecutor, + IDiscordRestGuildAPI guildApi) : IResponder +{ + private readonly ILogger _logger = logger.ForContext(); + + public async Task RespondAsync(IGuildMemberRemove evt, CancellationToken ct = default) + { + try + { + var embed = new EmbedBuilder() + .WithTitle("Member left") + .WithAuthor(evt.User.Tag(), iconUrl: evt.User.AvatarUrl()) + .WithColour(DiscordUtils.Orange) + .WithDescription($"<@{evt.User.ID}>") + .WithFooter($"ID: {evt.User.ID}") + .WithCurrentTimestamp(); + + var member = await memberCache.TryGetAsync(evt.GuildID, evt.User.ID); + if (member != null) + { + + } + + return Result.Success; + } + finally + { + await memberCache.RemoveAsync(evt.GuildID, evt.User.ID); + } + } +} \ No newline at end of file diff --git a/Catalogger.Backend/Cache/IMemberCache.cs b/Catalogger.Backend/Cache/IMemberCache.cs index 17edc57..72fa463 100644 --- a/Catalogger.Backend/Cache/IMemberCache.cs +++ b/Catalogger.Backend/Cache/IMemberCache.cs @@ -8,6 +8,7 @@ public interface IMemberCache public Task TryGetAsync(Snowflake guildId, Snowflake userId); public Task SetAsync(Snowflake guildId, IGuildMember member); public Task SetManyAsync(Snowflake guildId, IReadOnlyList members); + public Task RemoveAsync(Snowflake guildId, Snowflake userId); public Task IsGuildCachedAsync(Snowflake guildId); public Task MarkAsCachedAsync(Snowflake guildId); public Task MarkAsUncachedAsync(Snowflake guildId); diff --git a/Catalogger.Backend/Cache/InMemoryCache/AuditLogCache.cs b/Catalogger.Backend/Cache/InMemoryCache/AuditLogCache.cs new file mode 100644 index 0000000..ca904b3 --- /dev/null +++ b/Catalogger.Backend/Cache/InMemoryCache/AuditLogCache.cs @@ -0,0 +1,21 @@ +using System.Collections.Concurrent; +using Remora.Discord.API; +using Remora.Rest.Core; + +namespace Catalogger.Backend.Cache.InMemoryCache; + +public class AuditLogCache +{ + private readonly ConcurrentDictionary<(Snowflake, Snowflake), ModactionData> _kicks = new(); + private readonly ConcurrentDictionary<(Snowflake, Snowflake), ModactionData> _bans = new(); + + public void SetKick(Snowflake guildId, string targetId, Snowflake moderatorId, Optional reason) + { + if (!DiscordSnowflake.TryParse(targetId, out var targetUser)) + throw new CataloggerError("Target ID was not a valid snowflake"); + + _kicks[(guildId, targetUser.Value)] = new ModactionData(moderatorId, reason.OrDefault()); + } + + public record struct ModactionData(Snowflake ModeratorId, string? Reason); +} \ No newline at end of file diff --git a/Catalogger.Backend/Cache/InMemoryCache/InMemoryMemberCache.cs b/Catalogger.Backend/Cache/InMemoryCache/InMemoryMemberCache.cs index a3100d4..4eae1d0 100644 --- a/Catalogger.Backend/Cache/InMemoryCache/InMemoryMemberCache.cs +++ b/Catalogger.Backend/Cache/InMemoryCache/InMemoryMemberCache.cs @@ -19,7 +19,7 @@ public class InMemoryMemberCache : IMemberCache public Task SetAsync(Snowflake guildId, IGuildMember member) { if (!member.User.IsDefined()) - throw new CataloggerError("Member with undefined User passed to RedisMemberCache.SetAsync"); + throw new CataloggerError("Member with undefined User passed to InMemoryMemberCache.SetAsync"); _members[(guildId, member.User.Value.ID)] = member; return Task.CompletedTask; } @@ -30,6 +30,12 @@ public class InMemoryMemberCache : IMemberCache await SetAsync(guildId, member); } + public Task RemoveAsync(Snowflake guildId, Snowflake userId) + { + _members.Remove((guildId, userId), out _); + return Task.CompletedTask; + } + public Task IsGuildCachedAsync(Snowflake guildId) => Task.FromResult(_guilds.ContainsKey(guildId)); public Task MarkAsCachedAsync(Snowflake guildId) diff --git a/Catalogger.Backend/Cache/RedisCache/RedisMemberCache.cs b/Catalogger.Backend/Cache/RedisCache/RedisMemberCache.cs index d97c0c8..3856225 100644 --- a/Catalogger.Backend/Cache/RedisCache/RedisMemberCache.cs +++ b/Catalogger.Backend/Cache/RedisCache/RedisMemberCache.cs @@ -31,6 +31,9 @@ public class RedisMemberCache(RedisService redisService) : IMemberCache await redisService.SetHashAsync(GuildMembersKey(guildId), redisMembers, m => m.User.Id.ToString()); } + public async Task RemoveAsync(Snowflake guildId, Snowflake userId) => + await redisService.GetDatabase().HashDeleteAsync(GuildMembersKey(guildId), userId.ToString()); + public async Task IsGuildCachedAsync(Snowflake guildId) => await redisService.GetDatabase().SetContainsAsync(GuildCacheKey, guildId.ToString());