// Copyright (C) 2021-present sam (starshines.gay) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using Catalogger.Backend.Cache; using Catalogger.Backend.Database; using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Microsoft.EntityFrameworkCore; 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 InviteDeleteResponder( ILogger logger, DatabaseContext db, IInviteCache inviteCache, WebhookExecutorService webhookExecutor, IDiscordRestGuildAPI guildApi ) : IResponder { private readonly ILogger _logger = logger.ForContext(); public async Task RespondAsync(IInviteDelete evt, CancellationToken ct = default) { var guildId = evt.GuildID.Value; var dbDeleteCount = await db .Invites.Where(i => i.GuildId == guildId.Value && i.Code == evt.Code) .ExecuteDeleteAsync(ct); if (dbDeleteCount != 0) _logger.Information( "Deleted named invite {Invite} for guild {Guild}", evt.Code, guildId ); var invite = (await inviteCache.TryGetAsync(guildId)).FirstOrDefault(i => i.Code == evt.Code ); var invitesResult = await guildApi.GetGuildInvitesAsync(guildId, ct); if (!invitesResult.IsSuccess) { _logger.Error( "Could not fetch new invites for guild {GuildId}: {Error}", guildId, invitesResult.Error ); } else { await inviteCache.SetAsync(guildId, invitesResult.Entity); } if (invite == null) { _logger.Debug("Could not find invite {Invite} in cache, ignoring event", evt.Code); return Result.Success; } var embed = new EmbedBuilder() .WithTitle("Invite deleted") .WithDescription($"An invite (**{evt.Code}**) for <#{evt.ChannelID}> was deleted.") .WithColour(DiscordUtils.Red) .WithFooter($"Code: {evt.Code}"); embed.AddField("Created by", invite.Inviter.GetOrThrow().PrettyFormat()); embed.AddField("Uses", invite.Uses.ToString(), inline: true); embed.AddField( "Maximum uses", invite.MaxUses != 0 ? invite.MaxUses.ToString() : "Infinite", inline: true ); var guildConfig = await db.GetGuildAsync(guildId, false, ct); webhookExecutor.QueueLog( guildConfig, LogChannelType.InviteDelete, embed.Build().GetOrThrow() ); return Result.Success; } }