diff --git a/Catalogger.Backend/Bot/Responders/Invites/InviteCreateResponder.cs b/Catalogger.Backend/Bot/Responders/Invites/InviteCreateResponder.cs new file mode 100644 index 0000000..f97f3ec --- /dev/null +++ b/Catalogger.Backend/Bot/Responders/Invites/InviteCreateResponder.cs @@ -0,0 +1,70 @@ +using Catalogger.Backend.Cache; +using Catalogger.Backend.Database; +using Catalogger.Backend.Database.Queries; +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.Invites; + +public class InviteCreateResponder( + ILogger logger, + DatabaseContext db, + IInviteCache inviteCache, + IDiscordRestGuildAPI guildApi, + WebhookExecutorService webhookExecutor +) : IResponder +{ + private readonly ILogger _logger = logger.ForContext(); + + public async Task RespondAsync(IInviteCreate evt, CancellationToken ct = default) + { + var guildId = evt.GuildID.Value; + + var invitesResult = await guildApi.GetGuildInvitesAsync(guildId, ct); + if (!invitesResult.IsSuccess) + { + _logger.Error( + "Error fetching new invites for guild {GuildId}: {Error}", + guildId, + invitesResult.Error + ); + } + else + { + await inviteCache.SetAsync(guildId, invitesResult.Entity); + } + + var embed = new EmbedBuilder() + .WithTitle("Invite created") + .WithDescription($"A new invite (**{evt.Code}**) was created for <#{evt.ChannelID}>.") + .WithColour(DiscordUtils.Green) + .WithFooter($"Code: {evt.Code}"); + + embed.AddField("Created by", evt.Inviter.GetOrThrow().PrettyFormat()); + embed.AddField( + "Maximum uses", + evt.MaxUses != 0 ? evt.MaxUses.ToString() : "Infinite", + inline: true + ); + embed.AddField( + "Expires", + evt.MaxAge == TimeSpan.Zero + ? "Never" + : $"", + inline: true + ); + + var guildConfig = await db.GetGuildAsync(guildId, ct); + webhookExecutor.QueueLog( + guildConfig, + LogChannelType.InviteCreate, + embed.Build().GetOrThrow() + ); + return Result.Success; + } +} diff --git a/Catalogger.Backend/Extensions/DiscordExtensions.cs b/Catalogger.Backend/Extensions/DiscordExtensions.cs index 4a28e0e..3bacdf1 100644 --- a/Catalogger.Backend/Extensions/DiscordExtensions.cs +++ b/Catalogger.Backend/Extensions/DiscordExtensions.cs @@ -150,6 +150,9 @@ public static class DiscordExtensions return filterByIds != null ? sorted.Where(r => filterByIds.Contains(r.ID)) : sorted; } + public static string PrettyFormat(this IUser user, bool addMention = true) => + addMention ? $"{user.Tag()} <@{user.ID}>" : user.Tag(); + public static async Task TryFormatUserAsync( this UserCache userCache, Snowflake userId, @@ -157,12 +160,10 @@ public static class DiscordExtensions ) { var user = await userCache.GetUserAsync(userId); - if (addMention) - return user != null - ? $"{user.Tag()} <@{user.ID}>" - : $"*(unknown user {userId}) <@{userId}>*"; + if (user != null) + return user.PrettyFormat(addMention); - return user != null ? user.Tag() : $"*(unknown user {userId})*"; + return addMention ? $"*(unknown user {userId})* <@{userId}>" : $"*(unknown user {userId})*"; } public static int TextLength(this IEmbed embed)