// 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.Count == 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( [Option("role")] [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 ); guildConfig.KeyRoles.Add(role.ID.Value); await guildRepository.UpdateConfigAsync(guildId, guildConfig); return await feedbackService.ReplyAsync($"Added {role.Name} to this server's key roles!"); } [Command("remove")] [Description("Remove a key role.")] public async Task RemoveKeyRoleAsync( [Option("role")] [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 ); guildConfig.KeyRoles.Remove(role.ID.Value); await guildRepository.UpdateConfigAsync(guildId, guildConfig); return await feedbackService.ReplyAsync( $"Removed {role.Name} from this server's key roles!" ); } }