// 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.ComponentModel;
using Catalogger.Backend.Cache.InMemoryCache;
using Catalogger.Backend.Database.Repositories;
using Catalogger.Backend.Extensions;
using Remora.Commands.Attributes;
using Remora.Commands.Groups;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.API.Objects;
using Remora.Discord.Commands.Attributes;
using Remora.Discord.Commands.Feedback.Services;
using Remora.Discord.Commands.Services;
using Remora.Rest.Core;
using IResult = Remora.Results.IResult;
namespace Catalogger.Backend.Bot.Commands;
[Group("key-roles")]
[DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)]
public class KeyRoleCommands(
GuildRepository guildRepository,
ContextInjectionService contextInjection,
IFeedbackService feedbackService,
GuildCache guildCache,
RoleCache roleCache
) : CommandGroup
{
[Command("list")]
[Description("List this server's key roles.")]
public async Task ListKeyRolesAsync()
{
var (_, guildId) = contextInjection.GetUserAndGuild();
if (!guildCache.TryGet(guildId, out var guild))
throw new CataloggerError("Guild not in cache");
var guildRoles = roleCache.GuildRoles(guildId).ToList();
var guildConfig = await guildRepository.GetAsync(guildId);
if (guildConfig.KeyRoles.Length == 0)
return await feedbackService.ReplyAsync(
"There are no key roles to list. Add some with `/key-roles add`.",
isEphemeral: true
);
var description = string.Join(
"\n",
guildConfig.KeyRoles.Select(id =>
{
var role = guildRoles.FirstOrDefault(r => r.ID.Value == id);
return role != null ? $"- {role.Name} <@&{role.ID}>" : $"- unknown role {id}";
})
);
return await feedbackService.SendContextualEmbedAsync(
new Embed(
Title: $"Key roles for {guild.Name}",
Description: description,
Colour: DiscordUtils.Purple
)
);
}
[Command("add")]
[Description("Add a new key role.")]
public async Task AddKeyRoleAsync(
[Description("The role to add.")] [DiscordTypeHint(TypeHint.Role)] Snowflake roleId
)
{
var (_, guildId) = contextInjection.GetUserAndGuild();
var role = roleCache.GuildRoles(guildId).FirstOrDefault(r => r.ID == roleId);
if (role == null)
throw new CataloggerError("Role is not cached");
var guildConfig = await guildRepository.GetAsync(guildId);
if (guildConfig.KeyRoles.Any(id => role.ID.Value == id))
return await feedbackService.ReplyAsync(
$"{role.Name} is already a key role.",
isEphemeral: true
);
await guildRepository.AddKeyRoleAsync(guildId, role.ID);
return await feedbackService.ReplyAsync($"Added {role.Name} to this server's key roles!");
}
[Command("remove")]
[Description("Remove a key role.")]
public async Task RemoveKeyRoleAsync(
[Description("The role to remove.")] [DiscordTypeHint(TypeHint.Role)] Snowflake roleId
)
{
var (_, guildId) = contextInjection.GetUserAndGuild();
var role = roleCache.GuildRoles(guildId).FirstOrDefault(r => r.ID == roleId);
if (role == null)
throw new CataloggerError("Role is not cached");
var guildConfig = await guildRepository.GetAsync(guildId);
if (guildConfig.KeyRoles.All(id => role.ID != id))
return await feedbackService.ReplyAsync(
$"{role.Name} is already not a key role.",
isEphemeral: true
);
await guildRepository.RemoveKeyRoleAsync(guildId, role.ID);
return await feedbackService.ReplyAsync(
$"Removed {role.Name} from this server's key roles!"
);
}
}