Search in sources :

Example 1 with REQUESTS

use of com.mcmoddev.mmdbot.utilities.console.MMDMarkers.REQUESTS in project MMDBot by MinecraftModDevelopment.

the class EventReactionAdded method onMessageReactionAdd.

/**
 * On message reaction add.
 *
 * @param event the event
 */
@Override
public void onMessageReactionAdd(final MessageReactionAddEvent event) {
    handleRolePanels(event);
    if (!event.isFromGuild() || !event.isFromType(ChannelType.TEXT))
        return;
    final var channel = event.getTextChannel();
    final MessageHistory history = MessageHistory.getHistoryAround(channel, event.getMessageId()).limit(1).complete();
    final var message = history.getMessageById(event.getMessageId());
    if (message == null) {
        return;
    }
    final double removalThreshold = getConfig().getRequestsRemovalThreshold();
    final double warningThreshold = getConfig().getRequestsWarningThreshold();
    if (removalThreshold == 0 || warningThreshold == 0) {
        return;
    }
    final var guild = event.getGuild();
    final var guildId = guild.getIdLong();
    final var discussionChannel = guild.getTextChannelById(getConfig().getChannel("requests.discussion"));
    if (getConfig().getGuildID() == guildId && getConfig().getChannel("requests.main") == channel.getIdLong()) {
        final int freshnessDuration = getConfig().getRequestFreshnessDuration();
        if (freshnessDuration > 0) {
            final OffsetDateTime creationTime = message.getTimeCreated();
            final var now = OffsetDateTime.now();
            if (now.minusDays(freshnessDuration).isAfter(creationTime)) {
                // Do nothing if the request has gone past the freshness duration
                return;
            }
        }
        final List<Long> badReactionsList = getConfig().getBadRequestsReactions();
        final List<Long> goodReactionsList = getConfig().getGoodRequestsReactions();
        final List<Long> needsImprovementReactionsList = getConfig().getRequestsNeedsImprovementReactions();
        final var badReactions = Utils.getMatchingReactions(message, badReactionsList::contains);
        final List<Member> signedOffStaff = badReactions.stream().map(MessageReaction::retrieveUsers).flatMap(PaginationAction::stream).map(guild::getMember).filter(Objects::nonNull).filter(member -> member.hasPermission(Permission.KICK_MEMBERS)).toList();
        final var hasStaffSignoff = signedOffStaff.size() > 0;
        final int badReactionsCount = badReactions.stream().mapToInt(MessageReaction::getCount).sum();
        final int goodReactionsCount = Utils.getNumberOfMatchingReactions(message, goodReactionsList::contains);
        final int needsImprovementReactionsCount = Utils.getNumberOfMatchingReactions(message, needsImprovementReactionsList::contains);
        final double requestScore = (badReactionsCount + needsImprovementReactionsCount * 0.5) - goodReactionsCount;
        final User messageAuthor = message.getAuthor();
        if (requestScore >= removalThreshold) {
            // If the message has no staff signing off, skip the rest of the code
            if (!hasStaffSignoff) {
                // If it hasn't been logged about yet, log about it
                if (messagesAwaitingSignoff.add(message.getIdLong())) {
                    LOGGER.info(REQUESTS, "Request from {} has a score of {}, reaching removal threshold {}, " + "awaiting moderation approval.", messageAuthor, requestScore, removalThreshold);
                    final var logChannel = guild.getTextChannelById(getConfig().getChannel("events.requests_deletion"));
                    if (logChannel != null) {
                        final EmbedBuilder builder = new EmbedBuilder();
                        builder.setAuthor(messageAuthor.getAsTag(), messageAuthor.getEffectiveAvatarUrl());
                        builder.setTitle("Request awaiting moderator approval");
                        builder.appendDescription("Request from ").appendDescription(messageAuthor.getAsMention()).appendDescription(" has a score of " + requestScore).appendDescription(", reaching removal threshold of " + removalThreshold).appendDescription(" and is now awaiting moderator approval before deletion.");
                        builder.addField("Jump to Message", MarkdownUtil.maskedLink("Message in " + message.getTextChannel().getAsMention(), message.getJumpUrl()), true);
                        builder.setTimestamp(Instant.now());
                        builder.setColor(Color.YELLOW);
                        builder.setFooter("User ID: " + messageAuthor.getId());
                        logChannel.sendMessageEmbeds(builder.build()).allowedMentions(Collections.emptySet()).queue();
                    }
                }
                return;
            }
            LOGGER.info(REQUESTS, "Removed request from {} due to score of {} reaching removal threshold {}", messageAuthor, requestScore, removalThreshold);
            final Message response = new MessageBuilder().append(messageAuthor.getAsMention()).append(", ").append("your request has been found to be low quality by community review and has been removed.\n").append("Please see other requests for how to do it correctly.\n").appendFormat("It received %d 'bad' reactions, %d 'needs improvement' reactions, and %d " + "'good' reactions.", badReactionsCount, needsImprovementReactionsCount, goodReactionsCount).build();
            warnedMessages.remove(message);
            final var logChannel = guild.getTextChannelById(getConfig().getChannel("events.requests_deletion"));
            if (logChannel != null) {
                final EmbedBuilder builder = new EmbedBuilder();
                builder.setAuthor(messageAuthor.getAsTag(), messageAuthor.getEffectiveAvatarUrl());
                builder.setTitle("Deleted request by community review");
                builder.appendDescription("Deleted request from ").appendDescription(messageAuthor.getAsMention()).appendDescription(" which has a score of " + requestScore).appendDescription(", reaching removal threshold of " + removalThreshold).appendDescription(", and has been approved by moderators for deletion.");
                final String approvingMods = signedOffStaff.stream().map(s -> "%s (%s, id `%s`)".formatted(s.getAsMention(), s.getUser().getAsTag(), s.getId())).collect(Collectors.joining("\n"));
                builder.addField("Approving moderators", approvingMods, true);
                builder.setTimestamp(Instant.now());
                builder.setColor(Color.RED);
                builder.setFooter("User ID: " + messageAuthor.getId());
                logChannel.sendMessage(message.getContentRaw()).setEmbeds(builder.build()).allowedMentions(Collections.emptySet()).queue();
            }
            channel.deleteMessageById(event.getMessageId()).reason(String.format("Bad request: %d bad reactions, %d needs improvement reactions, %d good reactions", badReactionsCount, needsImprovementReactionsCount, goodReactionsCount)).flatMap(v -> {
                RestAction<Message> action = messageAuthor.openPrivateChannel().flatMap(privateChannel -> privateChannel.sendMessage(response));
                // If we can't DM the user, send it in the discussions channel instead.
                if (discussionChannel != null) {
                    action = action.onErrorFlatMap(throwable -> discussionChannel.sendMessage(response));
                }
                return action;
            }).queue();
        } else if (!warnedMessages.contains(message) && requestScore >= warningThreshold) {
            LOGGER.info(REQUESTS, "Warned user {} due to their request (message id: {}) score of {} reaching " + "warning threshold {}", messageAuthor, message.getId(), requestScore, warningThreshold);
            final Message response = new MessageBuilder().append(messageAuthor.getAsMention()).append(", ").append("your request is close to being removed by community review.\n").append("Please edit your message to bring it to a higher standard.\n").appendFormat("It has so far received %d 'bad' reactions, %d 'needs improvement' reactions, " + "and %d 'good' reactions.", badReactionsCount, needsImprovementReactionsCount, goodReactionsCount).build();
            warnedMessages.add(message);
            RestAction<Message> action = messageAuthor.openPrivateChannel().flatMap(privateChannel -> privateChannel.sendMessage(response));
            // If we can't DM the user, send it in the thread.
            if (discussionChannel != null) {
                action = action.onErrorFlatMap(throwable -> event.getGuild().getThreadChannelById(event.getMessageIdLong()).sendMessage(response));
            }
            action.queue();
        }
        // Remove messages under the removal threshold from the awaiting sign-off set
        if (requestScore < removalThreshold) {
            messagesAwaitingSignoff.remove(message.getIdLong());
        }
    }
}
Also used : Color(java.awt.Color) MessageReactionRemoveEvent(net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent) Permission(net.dv8tion.jda.api.Permission) Member(net.dv8tion.jda.api.entities.Member) MarkdownUtil(net.dv8tion.jda.api.utils.MarkdownUtil) ChannelType(net.dv8tion.jda.api.entities.ChannelType) User(net.dv8tion.jda.api.entities.User) MMDBot(com.mcmoddev.mmdbot.MMDBot) HashSet(java.util.HashSet) GenericMessageReactionEvent(net.dv8tion.jda.api.events.message.react.GenericMessageReactionEvent) MessageHistory(net.dv8tion.jda.api.entities.MessageHistory) Nonnull(javax.annotation.Nonnull) RestAction(net.dv8tion.jda.api.requests.RestAction) Message(net.dv8tion.jda.api.entities.Message) Utils(com.mcmoddev.mmdbot.utilities.Utils) ListenerAdapter(net.dv8tion.jda.api.hooks.ListenerAdapter) Set(java.util.Set) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) LOGGER(com.mcmoddev.mmdbot.MMDBot.LOGGER) MessageReactionAddEvent(net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) MMDBot.getConfig(com.mcmoddev.mmdbot.MMDBot.getConfig) List(java.util.List) OffsetDateTime(java.time.OffsetDateTime) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) PaginationAction(net.dv8tion.jda.api.requests.restaction.pagination.PaginationAction) MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) Collections(java.util.Collections) REQUESTS(com.mcmoddev.mmdbot.utilities.console.MMDMarkers.REQUESTS) User(net.dv8tion.jda.api.entities.User) Message(net.dv8tion.jda.api.entities.Message) MessageHistory(net.dv8tion.jda.api.entities.MessageHistory) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) OffsetDateTime(java.time.OffsetDateTime) Objects(java.util.Objects) PaginationAction(net.dv8tion.jda.api.requests.restaction.pagination.PaginationAction) Member(net.dv8tion.jda.api.entities.Member) RestAction(net.dv8tion.jda.api.requests.RestAction)

Aggregations

MMDBot (com.mcmoddev.mmdbot.MMDBot)1 LOGGER (com.mcmoddev.mmdbot.MMDBot.LOGGER)1 MMDBot.getConfig (com.mcmoddev.mmdbot.MMDBot.getConfig)1 Utils (com.mcmoddev.mmdbot.utilities.Utils)1 REQUESTS (com.mcmoddev.mmdbot.utilities.console.MMDMarkers.REQUESTS)1 Color (java.awt.Color)1 Instant (java.time.Instant)1 OffsetDateTime (java.time.OffsetDateTime)1 Collections (java.util.Collections)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Objects (java.util.Objects)1 Set (java.util.Set)1 Collectors (java.util.stream.Collectors)1 Nonnull (javax.annotation.Nonnull)1 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)1 MessageBuilder (net.dv8tion.jda.api.MessageBuilder)1 Permission (net.dv8tion.jda.api.Permission)1 ChannelType (net.dv8tion.jda.api.entities.ChannelType)1 Member (net.dv8tion.jda.api.entities.Member)1