feat: member role and key role logging
This commit is contained in:
parent
d445b5ba44
commit
a56cb87294
3 changed files with 140 additions and 6 deletions
|
|
@ -8,6 +8,7 @@ using Remora.Discord.API.Abstractions.Gateway.Events;
|
|||
using Remora.Discord.API.Abstractions.Objects;
|
||||
using Remora.Discord.Extensions.Embeds;
|
||||
using Remora.Discord.Gateway.Responders;
|
||||
using Remora.Rest.Core;
|
||||
using Remora.Results;
|
||||
|
||||
namespace Catalogger.Backend.Bot.Responders.MemberUpdate;
|
||||
|
|
@ -16,6 +17,7 @@ public class GuildMemberUpdateResponder(
|
|||
ILogger logger,
|
||||
DatabaseContext db,
|
||||
UserCache userCache,
|
||||
RoleCache roleCache,
|
||||
IMemberCache memberCache,
|
||||
WebhookExecutorService webhookExecutor,
|
||||
AuditLogCache auditLogCache
|
||||
|
|
@ -67,6 +69,14 @@ public class GuildMemberUpdateResponder(
|
|||
{
|
||||
return await HandleTimeoutAsync(newMember, ct);
|
||||
}
|
||||
|
||||
if (
|
||||
newMember.Roles.Except(oldMember.Roles).Any()
|
||||
|| oldMember.Roles.Except(newMember.Roles).Any()
|
||||
)
|
||||
{
|
||||
return await HandleRoleUpdateAsync(newMember, oldMember.Roles, ct);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -234,4 +244,120 @@ public class GuildMemberUpdateResponder(
|
|||
);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private async Task<Result> HandleRoleUpdateAsync(
|
||||
IGuildMemberUpdate member,
|
||||
IReadOnlyList<Snowflake> oldRoles,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
var guildConfig = await db.GetGuildAsync(member.GuildID, ct);
|
||||
var guildRoles = roleCache.GuildRoles(member.GuildID).ToList();
|
||||
|
||||
var keyRoleUpdate = new EmbedBuilder()
|
||||
.WithAuthor(member.User.Tag(), null, member.User.AvatarUrl())
|
||||
.WithTitle("Key roles added or removed")
|
||||
.WithDescription($"<@{member.User.ID}>")
|
||||
.WithColour(DiscordUtils.Purple)
|
||||
.WithFooter($"User ID: {member.User.ID}")
|
||||
.WithCurrentTimestamp();
|
||||
|
||||
var roleUpdate = new EmbedBuilder()
|
||||
.WithAuthor(member.User.Tag(), null, member.User.AvatarUrl())
|
||||
.WithTitle("Roles added or removed")
|
||||
.WithDescription($"<@{member.User.ID}>")
|
||||
.WithColour(DiscordUtils.Purple)
|
||||
.WithFooter($"User ID: {member.User.ID}")
|
||||
.WithCurrentTimestamp();
|
||||
|
||||
var addedRoles = member.Roles.Except(oldRoles).Select(s => s.Value).ToList();
|
||||
var removedRoles = oldRoles.Except(member.Roles).Select(s => s.Value).ToList();
|
||||
|
||||
if (addedRoles.Count != 0)
|
||||
{
|
||||
roleUpdate.AddField("Added", string.Join(", ", addedRoles.Select(id => $"<@&{id}>")));
|
||||
|
||||
// Add all added key roles to the log
|
||||
if (!addedRoles.Except(guildConfig.KeyRoles).Any())
|
||||
{
|
||||
var value = string.Join(
|
||||
"\n",
|
||||
addedRoles
|
||||
.Where(guildConfig.KeyRoles.Contains)
|
||||
.Select(id =>
|
||||
{
|
||||
var role = guildRoles.FirstOrDefault(r => r.ID.Value == id);
|
||||
return role != null ? $"{role.Name} <@&{role.ID}>" : $"<@&{id}>";
|
||||
})
|
||||
);
|
||||
|
||||
keyRoleUpdate.AddField("Added", value);
|
||||
}
|
||||
}
|
||||
|
||||
if (removedRoles.Count != 0)
|
||||
{
|
||||
roleUpdate.AddField(
|
||||
"Removed",
|
||||
string.Join(", ", removedRoles.Select(id => $"<@&{id}>"))
|
||||
);
|
||||
|
||||
// Add all removed key roles to the log
|
||||
if (!removedRoles.Except(guildConfig.KeyRoles).Any())
|
||||
{
|
||||
var value = string.Join(
|
||||
"\n",
|
||||
removedRoles
|
||||
.Where(guildConfig.KeyRoles.Contains)
|
||||
.Select(id =>
|
||||
{
|
||||
var role = guildRoles.FirstOrDefault(r => r.ID.Value == id);
|
||||
return role != null ? $"{role.Name} <@&{role.ID}>" : $"<@&{id}>";
|
||||
})
|
||||
);
|
||||
|
||||
keyRoleUpdate.AddField("Added", value);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any fields in the role update embed, we should send it
|
||||
if (roleUpdate.Fields.Count != 0)
|
||||
{
|
||||
webhookExecutor.QueueLog(
|
||||
guildConfig,
|
||||
LogChannelType.GuildMemberUpdate,
|
||||
roleUpdate.Build().GetOrThrow()
|
||||
);
|
||||
}
|
||||
|
||||
// Do the same for the key role update embed, but we also need to fetch the moderator that updated them
|
||||
if (keyRoleUpdate.Fields.Count != 0)
|
||||
{
|
||||
if (
|
||||
auditLogCache.TryGetMemberUpdate(member.GuildID, member.User.ID, out var actionData)
|
||||
)
|
||||
{
|
||||
var moderator = await userCache.GetUserAsync(actionData.ModeratorId);
|
||||
keyRoleUpdate.AddField(
|
||||
"Responsible moderator",
|
||||
moderator == null
|
||||
? $"*(unknown user {actionData.ModeratorId}) <@{actionData.ModeratorId}>*"
|
||||
: $"{moderator.Tag()} <@{moderator.ID}>"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyRoleUpdate.AddField("Responsible moderator", "*(unknown)*");
|
||||
}
|
||||
|
||||
// Finally, send the embed
|
||||
webhookExecutor.QueueLog(
|
||||
guildConfig,
|
||||
LogChannelType.GuildKeyRoleUpdate,
|
||||
keyRoleUpdate.Build().GetOrThrow()
|
||||
);
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue