using Remora.Discord.API.Abstractions.Gateway.Events; using Remora.Discord.API.Abstractions.Objects; using Remora.Rest.Core; using Serilog.Context; namespace Catalogger.Backend.Extensions; public static class LogUtils { public static IDisposable Enrich(T evt) where T : IGatewayEvent { var type = ("Event", typeof(T).Name); return evt switch { IMessageDelete md => PushProperties( type, ("GuildId", md.GuildID), ("ChannelId", md.ChannelID), ("MessageId", md.ID) ), IMessageUpdate mu => PushProperties( type, ("GuildId", mu.GuildID), ("ChannelId", mu.ChannelID), ("MessageId", mu.ID) ), IMessageCreate mc => PushProperties( type, ("GuildId", mc.GuildID), ("ChannelId", mc.ChannelID), ("MessageId", mc.ID) ), IMessageDeleteBulk mdb => PushProperties( type, ("GuildId", mdb.GuildID), ("ChannelId", mdb.ChannelID), ("MessageIds", mdb.IDs) ), IGuildRoleCreate grc => PushProperties( type, ("GuildId", grc.GuildID), ("RoleId", grc.Role.ID) ), IGuildRoleUpdate gru => PushProperties( type, ("GuildId", gru.GuildID), ("RoleId", gru.Role.ID) ), IGuildRoleDelete grd => PushProperties( type, ("GuildId", grd.GuildID), ("RoleId", grd.RoleID) ), IGuildMemberAdd gma => PushProperties( type, ("GuildId", gma.GuildID), ("UserId", gma.User.Map(u => u.ID)) ), IGuildMemberUpdate gmu => PushProperties( type, ("GuildId", gmu.GuildID), ("UserId", gmu.User.ID) ), IGuildMemberRemove gmr => PushProperties( type, ("GuildId", gmr.GuildID), ("UserId", gmr.User.ID) ), IInviteCreate ic => PushProperties( type, ("GuildId", ic.GuildID), ("ChannelId", ic.ChannelID), ("InviteCode", ic.Code) ), IInviteDelete id => PushProperties( type, ("GuildId", id.GuildID), ("ChannelId", id.ChannelID), ("Code", id.Code) ), IChannelCreate cc => PushProperties( type, ("GuildId", cc.GuildID), ("ChannelId", cc.ID) ), IChannelUpdate cu => PushProperties( type, ("GuildId", cu.GuildID), ("ChannelId", cu.ID) ), IChannelDelete cd => PushProperties( type, ("GuildId", cd.GuildID), ("ChannelId", cd.ID) ), IGuildAuditLogEntryCreate ale => PushProperties( type, ("GuildId", ale.GuildID), ("AuditLogEntryId", ale.ID), ("ActionType", ale.ActionType) ), IGuildBanAdd gba => PushProperties( type, ("GuildId", gba.GuildID), ("UserId", gba.User.ID) ), IGuildBanRemove gbr => PushProperties( type, ("GuildId", gbr.GuildID), ("UserId", gbr.User.ID) ), IGuildCreate gc => PushProperties( type, ("GuildId", gc.Guild.Match(g => g.ID, g => g.ID)) ), IGuildDelete gd => PushProperties(type, ("GuildId", gd.ID)), IGuildEmojisUpdate geu => PushProperties(type, ("GuildId", geu.GuildID)), IGuildMembersChunk gmc => PushProperties( type, ("GuildId", gmc.GuildID), ("MemberCount", gmc.Members.Count), ("ChunkIndex", gmc.ChunkIndex), ("ChunkCount", gmc.ChunkCount) ), IGuildUpdate gu => PushProperties(type, ("GuildId", gu.ID)), _ => PushProperties(type), }; } public static IDisposable PushProperties(params (string, object?)[] properties) => new MultiDisposable( properties .Select(p => { if (p.Item2 is Optional s) return LogContext.PushProperty(p.Item1, s.IsDefined() ? s.Value : null); return LogContext.PushProperty(p.Item1, p.Item2); }) .ToArray() ); private record MultiDisposable(IDisposable[] Entries) : IDisposable { public void Dispose() { foreach (var e in Entries) e.Dispose(); } } }