// 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 System.Net; using Catalogger.Backend.Api.Middleware; using Catalogger.Backend.Bot; using Catalogger.Backend.Database.Queries; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Remora.Discord.Extensions.Embeds; namespace Catalogger.Backend.Api; public partial class GuildsController { [HttpPost("leave")] public async Task LeaveGuildAsync(string id, [FromBody] LeaveGuildRequest req) { var (guildId, guild) = await ParseGuildAsync(id); if (guild.Name != req.Name) { throw new ApiError( HttpStatusCode.BadRequest, ErrorCode.BadRequest, "You must spell the server name correctly." ); } var guildConfig = await db.GetGuildAsync(guildId.Value); var logChannelId = webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildUpdate) ?? webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildMemberRemove); if (logChannelId != null) { var currentUser = await discordRequestService.GetMeAsync(CurrentToken); var embed = new EmbedBuilder() .WithTitle("Catalogger is leaving this server") .WithDescription( $"A moderator in this server ({currentUser.Tag}, <@{currentUser.Id}>) requested that Catalogger leave. " + "All data related to this server will be deleted." ) .WithColour(DiscordUtils.Red) .WithCurrentTimestamp() .Build() .GetOrThrow(); await webhookExecutor.SendLogAsync(logChannelId.Value, [embed], []); } else { _logger.Information( "Can't send guild {GuildId} a heads up when leaving as neither the guild update nor member remove events are logged", guildId ); } var leaveRes = await userApi.LeaveGuildAsync(guildId); if (!leaveRes.IsSuccess) { _logger.Error("Couldn't leave guild {GuildId}: {Error}", guildId, leaveRes.Error); throw new ApiError( HttpStatusCode.InternalServerError, ErrorCode.InternalServerError, "There was an error making Catalogger leave the server." ); } await using var tx = await db.Database.BeginTransactionAsync(); var inviteCount = await db .Invites.Where(i => i.GuildId == guildId.Value) .ExecuteDeleteAsync(); var watchlistCount = await db .Watchlists.Where(w => w.GuildId == guildId.Value) .ExecuteDeleteAsync(); var messageCount = await db .Messages.Where(m => m.GuildId == guildId.Value) .ExecuteDeleteAsync(); await db.Guilds.Where(g => g.Id == guildId.Value).ExecuteDeleteAsync(); await tx.CommitAsync(); _logger.Information( "Deleted {InviteCount} invites, {WatchlistCount} watchlist entries, and {MessageCount} messages for guild {GuildId}", inviteCount, watchlistCount, messageCount, guildId ); _logger.Information("Left guild {GuildId} and removed all data for it", guildId); return NoContent(); } public record LeaveGuildRequest(string Name); }