// 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; using Catalogger.Backend.Cache.InMemoryCache; using Catalogger.Backend.Database.Models; using Catalogger.Backend.Database.Repositories; using Catalogger.Backend.Extensions; using Remora.Commands.Attributes; using Remora.Commands.Groups; using Remora.Discord.API; 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.Discord.Pagination.Extensions; using Remora.Rest.Core; using IResult = Remora.Results.IResult; namespace Catalogger.Backend.Bot.Commands; [Group("watchlist")] [Description("Commands for managing the server's watchlist.")] [DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)] public class WatchlistCommands( WatchlistRepository watchlistRepository, GuildCache guildCache, IMemberCache memberCache, UserCache userCache, ContextInjectionService contextInjectionService, FeedbackService feedbackService ) : CommandGroup { [Command("add")] [Description("Add a user to the watchlist.")] public async Task AddAsync( [Description("The user to add")] IUser user, [Description("The reason for adding this user to the watchlist")] string reason ) { var (userId, guildId) = contextInjectionService.GetUserAndGuild(); var entry = await watchlistRepository.CreateEntryAsync(guildId, user.ID, userId, reason); return await feedbackService.ReplyAsync( $"Added {user.PrettyFormat()} to this server's watchlist, with the following reason:\n>>> {entry.Reason}" ); } [Command("remove")] [Description("Remove a user from the watchlist.")] public async Task RemoveAsync([Description("The user to remove")] IUser user) { var (userId, guildId) = contextInjectionService.GetUserAndGuild(); if (!await watchlistRepository.RemoveEntryAsync(guildId, user.ID)) { return await feedbackService.ReplyAsync( $"{user.PrettyFormat()} is not on the watchlist, so you can't remove them from it." ); } return await feedbackService.ReplyAsync( $"Removed {user.PrettyFormat()} from the watchlist!" ); } [Command("show")] [Description("Show the current watchlist.")] public async Task ShowAsync() { var (userId, guildId) = contextInjectionService.GetUserAndGuild(); if (!guildCache.TryGet(guildId, out var guild)) throw new CataloggerError("Guild was not cached"); var watchlist = await watchlistRepository.GetGuildWatchlistAsync(guildId); if (watchlist.Count == 0) return await feedbackService.ReplyAsync( "There are no entries on the watchlist right now." ); var fields = new List(); foreach (var entry in watchlist) fields.Add(await GenerateWatchlistEntryFieldAsync(guildId, entry)); return await feedbackService.SendContextualPaginatedMessageAsync( userId, DiscordUtils.PaginateFields( fields, title: $"Watchlist for {guild.Name} ({fields.Count})", fieldsPerPage: 5 ) ); } private async Task GenerateWatchlistEntryFieldAsync( Snowflake guildId, Watchlist entry ) { var user = await TryGetUserAsync(guildId, DiscordSnowflake.New(entry.UserId)); var fieldName = user != null ? user.Tag() : $"unknown user {entry.UserId}"; var moderator = await TryGetUserAsync(guildId, DiscordSnowflake.New(entry.ModeratorId)); var modName = moderator != null ? moderator.PrettyFormat() : $"*(unknown user {entry.ModeratorId})* <@{entry.ModeratorId}>"; return new EmbedField( Name: fieldName, Value: $""" **Moderator:** {modName} **Added:** **Reason:** >>> {entry.Reason} """ ); } private async Task TryGetUserAsync(Snowflake guildId, Snowflake userId) => (await memberCache.TryGetAsync(guildId, userId))?.User.Value ?? await userCache.GetUserAsync(userId); }