Search in sources :

Example 1 with MessageBuilder

use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.

the class WelcomeUtils method sendJoinLeaveMessage.

public static void sendJoinLeaveMessage(User user, Guild guild, TextChannel tc, List<String> extraMessages, String msg, boolean test) {
    var message = msg;
    if (!extraMessages.isEmpty()) {
        if (msg != null) {
            extraMessages.add(msg);
        }
        message = extraMessages.get(RANDOM.nextInt(extraMessages.size()));
        ;
    }
    if (tc != null && message != null) {
        if (!tc.canTalk()) {
            return;
        }
        if (message.contains("$(")) {
            message = new DynamicModifiers().mapFromJoinLeave("event", tc, user, guild).resolve(message);
        }
        var modIndex = message.indexOf(':');
        if (modIndex != -1) {
            // Wonky?
            var matcher = MODIFIER_PATTERN.matcher(message);
            var modifier = "none";
            // Find the first occurrence of a modifier (word:)
            if (matcher.find()) {
                modifier = matcher.group().replace(":", "");
            }
            var json = message.substring(modIndex + 1);
            var extra = "";
            // Somehow (?) this fails sometimes? I really dunno how, but sure.
            try {
                extra = message.substring(0, modIndex - modifier.length()).trim();
            } catch (Exception ignored) {
            }
            try {
                if (modifier.equals("embed")) {
                    EmbedJSON embed;
                    try {
                        embed = JsonDataManager.fromJson('{' + json + '}', EmbedJSON.class);
                    } catch (Exception e) {
                        tc.sendMessage(EmoteReference.ERROR2 + "The string\n```json\n{" + json + "}```\n" + "Is not a valid welcome/leave message (failed to Convert to EmbedJSON). Check the wiki for more information.").queue();
                        // So I know what is going on, regardless.
                        e.printStackTrace();
                        return;
                    }
                    var builder = new MessageBuilder().setEmbeds(embed.gen(null));
                    if (!extra.isEmpty()) {
                        builder.append(extra);
                    }
                    if (test) {
                        builder.append("\n**This is a test message. No mentions will be shown or resolved.**");
                    }
                    tc.sendMessage(builder.build()).allowedMentions(test ? EnumSet.noneOf(Message.MentionType.class) : EnumSet.of(Message.MentionType.USER, Message.MentionType.ROLE)).queue(success -> {
                    }, error -> tc.sendMessage("Failed to send join/leave message.").queue());
                    return;
                }
            } catch (Exception e) {
                if (e.getMessage().toLowerCase().contains("url must be a valid")) {
                    tc.sendMessage("Failed to send join/leave message: Wrong image URL in thumbnail, image, footer and/or author.").queue();
                } else {
                    tc.sendMessage("Failed to send join/leave message: Unknown error, try checking your message.").queue();
                    e.printStackTrace();
                }
            }
        }
        if (test) {
            message += "\n**This is a test message. No mentions will be shown or resolved.**";
        }
        tc.sendMessage(message).allowedMentions(test ? EnumSet.noneOf(Message.MentionType.class) : EnumSet.of(Message.MentionType.USER, Message.MentionType.ROLE)).queue(success -> {
        }, failure -> tc.sendMessage("Failed to send join/leave message.").queue());
    }
}
Also used : EmbedJSON(net.kodehawa.mantarobot.commands.custom.EmbedJSON) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) DynamicModifiers(net.kodehawa.mantarobot.commands.custom.legacy.DynamicModifiers)

Example 2 with MessageBuilder

use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.

the class BirthdayTask method handle.

public static void handle(int shardId) {
    final var bot = MantaroBot.getInstance();
    final var instant = Instant.now();
    try {
        final var cache = bot.getBirthdayCacher();
        // There's no cache to be seen here
        if (cache == null) {
            return;
        }
        // We haven't finished caching all members, somehow?
        if (!cache.isDone) {
            return;
        }
        final var start = System.currentTimeMillis();
        var membersAssigned = 0;
        var membersDivested = 0;
        final var jda = bot.getShardManager().getShardById(shardId);
        if (jda == null) {
            // To be fair, this shouldn't be possible as it only starts it with the shards it knows...
            return;
        }
        log.info("Checking birthdays in shard {} to assign roles...", jda.getShardInfo().getShardId());
        // Well, fuck, this was a day off. NYC time was 23:00 when Chicago time was at 00:00, so it checked the
        // birthdays for THE WRONG DAY. Heck.
        // 17-02-2022: Fuck again, I was using the wrong thing. Now it works, lol.
        final var timezone = ZonedDateTime.ofInstant(instant, ZoneId.of("America/Chicago"));
        // Example: 25-02
        final var now = timezone.format(dayMonthFormat);
        // Example: 02
        final var month = timezone.format(monthFormat);
        // Example: 01
        final var lastMonthTz = ZonedDateTime.ofInstant(instant, ZoneId.of("America/Chicago")).minusMonths(1);
        final var lastMonth = lastMonthTz.format(dateFormat);
        final var cached = cache.getCachedBirthdays();
        final var guilds = jda.getGuildCache();
        // Backoff sending: we need to backoff the birthday requests,
        // else we're gonna find ourselves quite often hitting ratelimits, which might slow the whole
        // bot down. Therefore, we're just gonna get all of the messages we need to send and *slowly*
        // send them over the course of a few minutes, instead of trying to send them all at once.
        Map<BirthdayGuildInfo, Queue<Message>> toSend = new HashMap<>();
        List<BirthdayRoleInfo> roleBackoffAdd = new ArrayList<>();
        List<BirthdayRoleInfo> roleBackoffRemove = new ArrayList<>();
        // For all current -cached- guilds.
        for (final var guild : guilds) {
            // This is quite a db spam, lol
            final var dbGuild = MantaroData.db().getGuild(guild);
            final var guildData = dbGuild.getData();
            // If we have a birthday guild and channel here, continue
            if (guildData.getBirthdayChannel() != null && guildData.getBirthdayRole() != null) {
                final var birthdayRole = guild.getRoleById(guildData.getBirthdayRole());
                final var channel = guild.getTextChannelById(guildData.getBirthdayChannel());
                if (channel != null && birthdayRole != null) {
                    if (!guild.getSelfMember().canInteract(birthdayRole))
                        // Go to next guild...
                        continue;
                    if (!channel.canTalk())
                        // cannot talk here...
                        continue;
                    if (guildData.getGuildAutoRole() != null && birthdayRole.getId().equals(guildData.getGuildAutoRole()))
                        // Birthday role is autorole role
                        continue;
                    if (birthdayRole.isPublicRole())
                        // Birthday role is public role
                        continue;
                    if (birthdayRole.isManaged())
                        // This was meant to be a bot role?
                        continue;
                    // Guild map is now created from allowed birthdays. This is a little hacky, but we don't really care.
                    // The other solution would have been just disabling this completely, which would have been worse.
                    // @formatter:off
                    Map<Long, BirthdayCacher.BirthdayData> guildMap = cached.entrySet().stream().filter(map -> guildData.getAllowedBirthdays().contains(String.valueOf(map.getKey()))).filter(map -> map.getValue().getBirthday().substring(3, 5).equals(month) || map.getValue().getBirthday().substring(3, 5).equals(lastMonth)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                    // @formatter:on
                    var birthdayAnnouncerText = new MessageBuilder();
                    birthdayAnnouncerText.append("**New birthdays for today, wish them Happy Birthday!**").append("\n\n");
                    int birthdayNumber = 0;
                    List<Long> nullMembers = new ArrayList<>();
                    for (var data : guildMap.entrySet()) {
                        var birthday = data.getValue().getBirthday();
                        if (guildData.getBirthdayBlockedIds().contains(String.valueOf(data.getKey()))) {
                            continue;
                        }
                        if (birthday == null) {
                            log.debug("Birthday is null? Continuing...");
                            nullMembers.add(data.getKey());
                            continue;
                        }
                        // This needs to be a retrieveMemberById call, sadly. This will get cached, though.
                        Member member;
                        try {
                            // This is expensive!
                            member = guild.retrieveMemberById(data.getKey(), false).complete();
                        } catch (Exception ex) {
                            nullMembers.add(data.getKey());
                            continue;
                        }
                        // Make sure we announce on March 1st for birthdays on February 29 if the current
                        // year is not a leap year.
                        var compare = birthday.substring(0, 5);
                        if (compare.equals("29-02") && !Year.isLeap(LocalDate.now().getYear())) {
                            compare = "28-02";
                        }
                        if (compare.equals(now)) {
                            log.debug("Assigning birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
                            var tempBirthdayMessage = String.format(EmoteReference.POPPER + "**%s is a year older now! Wish them a happy birthday.** :tada:", member.getEffectiveName());
                            if (guildData.getBirthdayMessage() != null) {
                                tempBirthdayMessage = guildData.getBirthdayMessage().replace("$(user)", member.getEffectiveName()).replace("$(usermention)", member.getAsMention()).replace("$(tag)", member.getUser().getAsTag());
                            }
                            // Variable used in lambda expression should be final or effectively final...
                            final var birthdayMessage = tempBirthdayMessage;
                            if (!member.getRoles().contains(birthdayRole)) {
                                log.debug("Backing off adding birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
                                // We can pretty much do all of this only based on the IDs
                                roleBackoffAdd.add(new BirthdayRoleInfo(guild.getId(), member.getId(), birthdayRole));
                                birthdayAnnouncerText.append(birthdayMessage).append("\n");
                                membersAssigned++;
                                birthdayNumber++;
                                Metrics.BIRTHDAY_COUNTER.inc();
                            }
                        } else {
                            // day passed
                            if (member.getRoles().contains(birthdayRole)) {
                                log.debug("Backing off removing birthday role on guild {} (M: {})", guild.getId(), member.getEffectiveName());
                                roleBackoffRemove.add(new BirthdayRoleInfo(guild.getId(), member.getId(), birthdayRole));
                                membersDivested++;
                            }
                        }
                    }
                    if (birthdayNumber != 0) {
                        toSend.put(new BirthdayGuildInfo(guild.getId(), channel.getId()), birthdayAnnouncerText.buildAll(MessageBuilder.SplitPolicy.NEWLINE));
                    }
                    // If any of the member lookups to discord returned null, remove them.
                    if (!nullMembers.isEmpty()) {
                        guildData.getAllowedBirthdays().removeAll(nullMembers.stream().map(String::valueOf).collect(Collectors.toList()));
                        dbGuild.save();
                    }
                }
            }
        }
        final var end = System.currentTimeMillis();
        log.info("{} (birthdays): people assigned: {}, people divested: {}, took {}ms", jda.getShardInfo(), membersAssigned, membersDivested, (end - start));
        // A poll inside a pool?
        // Send the backoff sending comment above, this basically avoids hitting
        // discord with one billion requests at once.
        final var backoff = 400;
        final var roleBackoff = 100;
        backOffPool.submit(() -> {
            log.info("{} (birthdays): Backoff messages: {}. Sending them with {}ms backoff.", jda.getShardInfo(), toSend.size(), backoff);
            final var startMessage = System.currentTimeMillis();
            for (var entry : toSend.entrySet()) {
                try {
                    final var info = entry.getKey();
                    final var guildId = info.guildId;
                    final var channelId = info.channelId;
                    final var messages = entry.getValue();
                    final var guild = bot.getShardManager().getGuildById(guildId);
                    if (guild == null)
                        continue;
                    final var channel = guild.getTextChannelById(channelId);
                    if (channel == null)
                        continue;
                    messages.forEach(message -> channel.sendMessage(message).allowedMentions(EnumSet.of(Message.MentionType.USER, Message.MentionType.CHANNEL, Message.MentionType.ROLE, Message.MentionType.EMOTE)).queue());
                    // If 100 guilds (about 1/10th of all the shard guilds! so very unlikely) do
                    // get a birthday now, the maximum delay will be 40,000ms, which is 40 seconds.
                    // Not much of an issue for the end user, but avoid sending too many requests
                    // to discord at once. If half of all the guilds in the shard do, the delay
                    // will be about 200,000ms, so 2 minutes.
                    Thread.sleep(backoff);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            final var endMessage = System.currentTimeMillis();
            toSend.clear();
            log.info("Sent all birthday backoff messages, backoff was {}ms, took {}ms", backoff, endMessage - startMessage);
        });
        backOffRolePool.submit(() -> {
            log.info("{} (birthdays): Backoff roles (add): {}. Sending them with {}ms backoff.", jda.getShardInfo(), roleBackoffAdd.size(), roleBackoff);
            final var startRole = System.currentTimeMillis();
            for (var roleInfo : roleBackoffAdd) {
                try {
                    var guild = bot.getShardManager().getGuildById(roleInfo.guildId);
                    if (guild == null)
                        continue;
                    guild.addRoleToMember(roleInfo.memberId, roleInfo.role).reason(modLogMessage).queue();
                    Thread.sleep(roleBackoff);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            log.info("{} (birthdays): Backoff roles (remove): {}. Sending them with {}ms backoff.", jda.getShardInfo(), roleBackoffRemove.size(), roleBackoff);
            for (var roleInfo : roleBackoffRemove) {
                try {
                    var guild = bot.getShardManager().getGuildById(roleInfo.guildId);
                    if (guild == null)
                        continue;
                    guild.removeRoleFromMember(roleInfo.memberId, roleInfo.role).reason(modLogMessage).queue();
                    Thread.sleep(roleBackoff);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            final var endRole = System.currentTimeMillis();
            roleBackoffAdd.clear();
            roleBackoffRemove.clear();
            log.info("{} (birthdays): All roles done (add and removal), backoff was {}ms. Took {}ms", jda.getShardInfo(), roleBackoff, endRole - startRole);
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Also used : ThreadFactoryBuilder(com.google.common.util.concurrent.ThreadFactoryBuilder) Message(net.dv8tion.jda.api.entities.Message) java.util(java.util) Logger(org.slf4j.Logger) LoggerFactory(org.slf4j.LoggerFactory) Member(net.dv8tion.jda.api.entities.Member) Metrics(net.kodehawa.mantarobot.utils.exporters.Metrics) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) MantaroBot(net.kodehawa.mantarobot.MantaroBot) java.time(java.time) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) Role(net.dv8tion.jda.api.entities.Role) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) DateTimeFormatter(java.time.format.DateTimeFormatter) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) MantaroData(net.kodehawa.mantarobot.data.MantaroData) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) Member(net.dv8tion.jda.api.entities.Member)

Example 3 with MessageBuilder

use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.

the class ImageActionCmd method call.

@Override
protected void call(Context ctx, String content) {
    if (!RatelimitUtils.ratelimit(rateLimiter, ctx, null)) {
        return;
    }
    var languageContext = ctx.getGuildLanguageContext();
    var random = "";
    try {
        if (type != null) {
            var result = weebapi.getRandomImageByType(type, false, "gif");
            var image = result.getKey();
            if (image == null) {
                ctx.sendLocalized("commands.action.error_retrieving", EmoteReference.SAD);
                return;
            }
            images = Collections.singletonList(image);
            // Guaranteed random selection :^).
            random = images.get(0);
        } else {
            if (images.isEmpty()) {
                ctx.sendLocalized("commands.action.no_type", EmoteReference.ERROR);
                return;
            }
            random = images.get(rand.nextInt(images.size()));
        }
    } catch (Exception e) {
        ctx.sendLocalized("commands.action.error_retrieving", EmoteReference.ERROR);
        return;
    }
    try {
        var mentionedMembers = ctx.getMentionedMembers();
        if (mentionedMembers.isEmpty()) {
            ctx.sendLocalized("commands.action.no_mention", EmoteReference.ERROR);
            return;
        }
        boolean filtered = false;
        if (mentionedMembers.size() == 1) {
            final var dbUser = ctx.getDBUser(mentionedMembers.get(0).getId());
            if (dbUser.getData().isActionsDisabled()) {
                ctx.sendLocalized("commands.action.actions_disabled", EmoteReference.ERROR);
                return;
            }
        } else {
            var filter = mentionedMembers.stream().filter(member -> ctx.getDBUser(member).getData().isActionsDisabled()).collect(Collectors.toList());
            // Needs to be mutable.
            mentionedMembers = new ArrayList<>(mentionedMembers);
            if (mentionedMembers.removeAll(filter)) {
                filtered = true;
            }
            if (mentionedMembers.isEmpty()) {
                ctx.sendLocalized("commands.action.no_mention_disabled", EmoteReference.ERROR);
                return;
            }
        }
        var toSend = new MessageBuilder().append(emoji).append(String.format(languageContext.get(format), "**%s**".formatted(noMentions(mentionedMembers)), "**%s**".formatted(ctx.getMember().getEffectiveName())));
        if (swapNames) {
            toSend = new MessageBuilder().append(emoji).append(String.format(languageContext.get(format), "**%s**".formatted(ctx.getMember().getEffectiveName()), "**%s**".formatted(noMentions(mentionedMembers))));
        }
        if (isLonely(ctx)) {
            toSend = new MessageBuilder().append("**").append(languageContext.get(lonelyLine)).append("**");
        }
        if (isMentioningBot(ctx)) {
            toSend = new MessageBuilder().append("**").append(languageContext.get(botLine)).append("**");
        }
        if (filtered) {
            toSend.append("\n").append(String.format(languageContext.get("commands.action.filtered"), EmoteReference.WARNING));
        }
        var member = ctx.getMember();
        toSend.setEmbeds(new EmbedBuilder().setColor(ctx.getMemberColor()).setImage(random).build());
        ctx.getChannel().sendMessage(toSend.build()).queue();
    } catch (Exception e) {
        e.printStackTrace();
        ctx.sendLocalized("commands.action.permission_or_unexpected_error", EmoteReference.ERROR);
    }
}
Also used : Color(java.awt.Color) java.util(java.util) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) NoArgsCommand(net.kodehawa.mantarobot.core.modules.commands.NoArgsCommand) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Member(net.dv8tion.jda.api.entities.Member) Collectors(java.util.stream.Collectors) TimeUnit(java.util.concurrent.TimeUnit) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) MessageBuilder(net.dv8tion.jda.api.MessageBuilder)

Example 4 with MessageBuilder

use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.

the class ImageGame method sendEmbedImage.

protected RestAction<Message> sendEmbedImage(MessageChannel channel, String url, Consumer<EmbedBuilder> embedConfigurator) {
    var eb = new EmbedBuilder();
    embedConfigurator.accept(eb);
    eb.setImage("attachment://image.png").setColor(Color.PINK);
    var message = new MessageBuilder().setEmbeds(eb.build());
    return channel.sendMessage(message.build()).addFile(cache.getInput(url), "image.png");
}
Also used : EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) MessageBuilder(net.dv8tion.jda.api.MessageBuilder)

Example 5 with MessageBuilder

use of net.dv8tion.jda.api.MessageBuilder in project MantaroBot by Mantaro.

the class CustomCommandHandler method handle.

public void handle(boolean preview) {
    if (!processResponse())
        return;
    if (specialHandling())
        return;
    if (response.startsWith("v3:")) {
        CCv3.process(prefixUsed, ctx, new Parser(response.substring(3)).parse(), preview);
        return;
    }
    MessageBuilder builder = new MessageBuilder().setContent(filtered.matcher(response).replaceAll("-filtered regex-"));
    builder.setActionRows(ActionRow.of(Button.primary("yes", ctx.getLanguageContext().get("commands.custom.custom_notice")).asDisabled()));
    if (preview) {
        builder.append("\n\n").append(EmoteReference.WARNING).append("**This is a preview of how a CC with this content would look like, ALL MENTIONS ARE DISABLED ON THIS MODE.**\n").append("`Command preview requested by: ").append(ctx.getAuthor().getAsTag()).append("`");
        builder.denyMentions(Message.MentionType.ROLE, Message.MentionType.USER, Message.MentionType.EVERYONE, Message.MentionType.HERE);
    } else {
        builder.denyMentions(Message.MentionType.ROLE, Message.MentionType.EVERYONE, Message.MentionType.HERE);
    }
    ctx.send(builder.build());
}
Also used : MessageBuilder(net.dv8tion.jda.api.MessageBuilder) Parser(net.kodehawa.mantarobot.commands.custom.v3.Parser)

Aggregations

MessageBuilder (net.dv8tion.jda.api.MessageBuilder)10 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)6 Collectors (java.util.stream.Collectors)4 Member (net.dv8tion.jda.api.entities.Member)4 java.util (java.util)3 Message (net.dv8tion.jda.api.entities.Message)3 MantaroData (net.kodehawa.mantarobot.data.MantaroData)3 EmoteReference (net.kodehawa.mantarobot.utils.commands.EmoteReference)3 Color (java.awt.Color)2 TimeUnit (java.util.concurrent.TimeUnit)2 MessageEmbed (net.dv8tion.jda.api.entities.MessageEmbed)2 Role (net.dv8tion.jda.api.entities.Role)2 CommandCategory (net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory)2 Context (net.kodehawa.mantarobot.core.modules.commands.base.Context)2 HelpContent (net.kodehawa.mantarobot.core.modules.commands.help.HelpContent)2 IncreasingRateLimiter (net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter)2 RatelimitUtils (net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils)2 Subscribe (com.google.common.eventbus.Subscribe)1 ThreadFactoryBuilder (com.google.common.util.concurrent.ThreadFactoryBuilder)1 java.time (java.time)1