Search in sources :

Example 1 with MessageReaction

use of net.dv8tion.jda.api.entities.MessageReaction in project Gary by help-chat.

the class EventUtils method pullReaction.

public static Future<MessageReaction> pullReaction(Message message, User user) {
    JDA jda = message.getJDA();
    CompletableFuture<MessageReaction> future = new CompletableFuture<>();
    GuildMessageReactionAddEvent e = (GuildMessageReactionAddEvent) pullEvent(EventsEnum.MESSAGE_REACTION_ADD, jda);
    while (message.getChannel().retrieveMessageById(e.getMessageId()).complete() != message || e.getUser() != user) {
        e = (GuildMessageReactionAddEvent) pullEvent(EventsEnum.MESSAGE_REACTION_ADD, jda);
    }
    future.complete(e.getReaction());
    return future;
}
Also used : MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) CompletableFuture(java.util.concurrent.CompletableFuture) JDA(net.dv8tion.jda.api.JDA) GuildMessageReactionAddEvent(net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent)

Example 2 with MessageReaction

use of net.dv8tion.jda.api.entities.MessageReaction in project Gary by help-chat.

the class RMSReactionHandler method execute.

@Override
protected void execute(GenericEvent event) {
    GuildMessageReactionAddEvent e = (GuildMessageReactionAddEvent) event;
    if (e.getChannel().getName().equalsIgnoreCase("rate-my-server") && !e.getUser().isBot()) {
        Message message = e.getChannel().retrieveMessageById(e.getMessageId()).complete();
        List<MessageReaction> reactions = new ArrayList<>(message.getReactions());
        // this exception will never happen, so can be ignored
        // noinspection OptionalGetWithoutIsPresent
        reactions.remove(reactions.stream().filter(r -> r.toString().equals(e.getReaction().toString())).findFirst().get());
        if (reactions.stream().anyMatch(d -> d.retrieveUsers().complete().contains(e.getUser()))) {
            e.getReaction().removeReaction(e.getUser()).queue();
        }
    }
}
Also used : GEvent(me.piggypiglet.gary.core.handlers.GEvent) Message(net.dv8tion.jda.api.entities.Message) List(java.util.List) GuildMessageReactionAddEvent(net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent) EventsEnum(me.piggypiglet.gary.core.objects.enums.EventsEnum) MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) ArrayList(java.util.ArrayList) MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) Message(net.dv8tion.jda.api.entities.Message) GuildMessageReactionAddEvent(net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent) ArrayList(java.util.ArrayList)

Example 3 with MessageReaction

use of net.dv8tion.jda.api.entities.MessageReaction in project Ninbot by Nincodedo.

the class PollResultsAnnouncer method getPollResultsMessage.

private String getPollResultsMessage() {
    var newMessage = pollMessage.getChannel().retrieveMessageById(pollMessage.getId()).complete();
    int highCount = 0;
    List<String> winningChoices = new ArrayList<>();
    List<MessageReaction> reactions = newMessage.getReactions();
    for (int i = 0; i < reactions.size() && i < poll.getChoices().size(); i++) {
        MessageReaction reaction = reactions.get(i);
        if (reaction.getCount() == highCount) {
            winningChoices.add(poll.getChoices().get(i));
        }
        if (reaction.getCount() > highCount) {
            highCount = reaction.getCount();
            winningChoices.clear();
            winningChoices.add(poll.getChoices().get(i));
        }
    }
    var resourceBundle = poll.getResourceBundle();
    String pollClosedMessage = resourceBundle.getString("poll.announce.closed");
    if (highCount <= 1) {
        poll.setResult(resourceBundle.getString("poll.announce.noonevoted") + pollClosedMessage);
    } else if (winningChoices.size() == 1) {
        poll.setResult("\"" + winningChoices.get(0) + "\"" + resourceBundle.getString("poll.announce.hadmostvotes") + (highCount - 1) + resourceBundle.getString("poll.announce.votes") + pollClosedMessage);
    } else if (winningChoices.size() > 1) {
        poll.setResult(String.format(resourceBundle.getString("poll.announce.tie"), listWinners(winningChoices), highCount - 1) + pollClosedMessage);
    }
    return poll.getResult();
}
Also used : MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) ArrayList(java.util.ArrayList)

Example 4 with MessageReaction

use of net.dv8tion.jda.api.entities.MessageReaction in project MMDBot by MinecraftModDevelopment.

the class Utils method getMatchingReactions.

/**
 * Gets reactions matching a predicate
 *
 * @param message   The message we are getting the matching reactions from.
 * @param predicate The predicate
 * @return The matching reactions.
 */
public static List<MessageReaction> getMatchingReactions(final Message message, final LongPredicate predicate) {
    List<MessageReaction> reactions = message.getReactions();
    List<MessageReaction> matches = new ArrayList<>();
    for (MessageReaction react : reactions) {
        Emote emote = react.getReactionEmote().isEmote() ? react.getReactionEmote().getEmote() : null;
        if (emote != null)
            if (predicate.test(emote.getIdLong()))
                matches.add(react);
    }
    return matches;
}
Also used : MessageReaction(net.dv8tion.jda.api.entities.MessageReaction) Emote(net.dv8tion.jda.api.entities.Emote) ArrayList(java.util.ArrayList)

Example 5 with MessageReaction

use of net.dv8tion.jda.api.entities.MessageReaction 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

MessageReaction (net.dv8tion.jda.api.entities.MessageReaction)12 ArrayList (java.util.ArrayList)5 Member (net.dv8tion.jda.api.entities.Member)5 Instant (java.time.Instant)4 Message (net.dv8tion.jda.api.entities.Message)4 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)3 Emote (net.dv8tion.jda.api.entities.Emote)3 Guild (net.dv8tion.jda.api.entities.Guild)3 ChronoUnit (java.time.temporal.ChronoUnit)2 java.util (java.util)2 Objects (java.util.Objects)2 TimeUnit (java.util.concurrent.TimeUnit)2 JDA (net.dv8tion.jda.api.JDA)2 MessageBuilder (net.dv8tion.jda.api.MessageBuilder)2 Permission (net.dv8tion.jda.api.Permission)2 User (net.dv8tion.jda.api.entities.User)2 GuildMessageReactionAddEvent (net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent)2 MessageReactionAddEvent (net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent)2