// 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.Database.Models;
using Microsoft.AspNetCore.Mvc;
using NodaTime;
using Remora.Discord.API;
namespace Catalogger.Backend.Api;
public partial class GuildsController
{
[Authorize]
[HttpGet("config")]
public async Task ExportConfigAsync(string id)
{
var (guildId, _) = await ParseGuildAsync(id);
var guildConfig = await guildRepository.GetAsync(guildId);
return Ok(await ToExport(guildConfig));
}
[Authorize]
[HttpPost("config")]
public async Task ImportConfigAsync(string id, [FromBody] ConfigExport export)
{
var (guildId, _) = await ParseGuildAsync(id);
if (export.Id != guildId.Value)
throw new ApiError(
HttpStatusCode.BadRequest,
ErrorCode.BadRequest,
"This backup is not from this server."
);
// Filter invites to *only* those that exist for this guild.
// Blame past me for not making (code, guild_id) a unique index >:|
var cachedInvites = (await inviteCache.TryGetAsync(guildId)).ToList();
var invites = export.Invites.Where(i => cachedInvites.Any(ci => i.Code == ci.Code));
await guildRepository.ImportConfigAsync(
guildId.Value,
export.Channels.ToChannelConfig(),
export.Channels.ToMessageConfig(),
export.BannedSystems,
export.KeyRoles
);
await inviteRepository.ImportInvitesAsync(
guildId,
invites.Select(i => new Invite
{
Code = i.Code,
Name = i.Name,
GuildId = guildId.Value,
})
);
await watchlistRepository.ImportWatchlistAsync(
guildId,
export.Watchlist.Select(w => new Watchlist
{
GuildId = guildId.Value,
UserId = w.UserId,
ModeratorId = w.ModeratorId,
AddedAt = w.AddedAt,
Reason = w.Reason,
})
);
return NoContent();
}
private async Task ToExport(Database.Models.Guild config)
{
var id = DiscordSnowflake.New(config.Id);
var invites = await inviteRepository.GetGuildInvitesAsync(id);
var watchlist = await watchlistRepository.GetGuildWatchlistAsync(id);
return new ConfigExport(
config.Id,
ChannelsBackup.FromGuildConfig(config),
config.BannedSystems,
config.KeyRoles,
invites.Select(i => new InviteExport(i.Code, i.Name)),
watchlist.Select(w => new WatchlistExport(w.UserId, w.AddedAt, w.ModeratorId, w.Reason))
);
}
}