Search in sources :

Example 1 with IncreasingRateLimiter

use of net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter in project MantaroBot by Mantaro.

the class WaifuCmd method waifu.

@Subscribe
public void waifu(CommandRegistry cr) {
    IncreasingRateLimiter rl = new IncreasingRateLimiter.Builder().limit(1).spamTolerance(2).cooldown(5, TimeUnit.SECONDS).maxCooldown(5, TimeUnit.SECONDS).randomIncrement(true).pool(MantaroData.getDefaultJedisPool()).prefix("waifu").build();
    TreeCommand waifu = cr.register("waifu", new TreeCommand(CommandCategory.CURRENCY) {

        @Override
        public Command defaultTrigger(Context ctx, String mainCommand, String commandName) {
            return new SubCommand() {

                @Override
                protected void call(Context ctx, I18nContext languageContext, String content) {
                    // IMPLEMENTATION NOTES FOR THE WAIFU SYSTEM
                    // You get 3 free slots to put "waifus" in.
                    // Each extra slot (up to 9) costs exponentially more than the last one (2x more than the costs of the last one)
                    // Every waifu has a "claim" price which increases in the following situations:
                    // For every 100000 money owned, it increases by 3% base value (base: 1500)
                    // For every 10 badges, it increases by 20% base value.
                    // For every 1000 experience, the value increases by 20% of the base value.
                    // After all those calculations are complete,
                    // the value then is calculated using final * (reputation scale / 10)
                    // where reputation scale goes up by 1 every 10 reputation points.
                    // Maximum waifu value is Integer.MAX_VALUE.
                    // Having a common waifu with your married partner will increase some marriage stats.
                    // If you claim a waifu, and then your waifu claims you, that will unlock the "Mutual" achievement.
                    // If the waifu status is mutual,
                    // the MP game boost will go up by 20% and giving your daily to that waifu will increase the amount of money that your
                    // waifu will receive.
                    final var opts = ctx.getOptionalArguments();
                    // Default call will bring out the waifu list.
                    final var dbUser = ctx.getDBUser();
                    final var userData = dbUser.getData();
                    final var player = ctx.getPlayer();
                    if (player.getData().isWaifuout()) {
                        ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                        return;
                    }
                    if (!ctx.getSelfMember().hasPermission(ctx.getChannel(), Permission.MESSAGE_EMBED_LINKS)) {
                        ctx.sendLocalized("general.missing_embed_permissions");
                        return;
                    }
                    final var description = userData.getWaifus().isEmpty() ? languageContext.get("commands.waifu.waifu_header") + "\n" + languageContext.get("commands.waifu.no_waifu") : languageContext.get("commands.waifu.waifu_header");
                    final var waifusEmbed = new EmbedBuilder().setAuthor(languageContext.get("commands.waifu.header"), null, ctx.getAuthor().getEffectiveAvatarUrl()).setThumbnail("https://i.imgur.com/2JlMtCe.png").setColor(Color.CYAN).setFooter(languageContext.get("commands.waifu.footer").formatted(userData.getWaifus().size(), userData.getWaifuSlots() - userData.getWaifus().size()), null);
                    if (userData.getWaifus().isEmpty()) {
                        waifusEmbed.setDescription(description);
                        ctx.send(waifusEmbed.build());
                        return;
                    }
                    final var id = opts.containsKey("id");
                    List<String> toRemove = new ArrayList<>();
                    List<MessageEmbed.Field> fields = new LinkedList<>();
                    for (String waifu : userData.getWaifus().keySet()) {
                        // This fixes the issue of cross-node waifus not appearing.
                        User user = ctx.retrieveUserById(waifu);
                        if (user == null) {
                            fields.add(new MessageEmbed.Field("%sUnknown User (ID: %s)".formatted(EmoteReference.BLUE_SMALL_MARKER, waifu), languageContext.get("commands.waifu.value_format") + " unknown\n" + languageContext.get("commands.waifu.value_b_format") + " " + userData.getWaifus().get(waifu) + languageContext.get("commands.waifu.credits_format"), false));
                        } else {
                            Player waifuClaimed = ctx.getPlayer(user);
                            if (waifuClaimed.getData().isWaifuout()) {
                                toRemove.add(waifu);
                                continue;
                            }
                            fields.add(new MessageEmbed.Field(EmoteReference.BLUE_SMALL_MARKER + user.getName() + (!userData.isPrivateTag() ? "#" + user.getDiscriminator() : ""), (id ? languageContext.get("commands.waifu.id") + " " + user.getId() + "\n" : "") + languageContext.get("commands.waifu.value_format") + " " + waifuClaimed.getData().getWaifuCachedValue() + " " + languageContext.get("commands.waifu.credits_format") + "\n" + languageContext.get("commands.waifu.value_b_format") + " " + userData.getWaifus().get(waifu) + languageContext.get("commands.waifu.credits_format"), false));
                        }
                    }
                    final var toSend = languageContext.get("commands.waifu.description_header").formatted(userData.getWaifuSlots()) + description;
                    DiscordUtils.sendPaginatedEmbed(ctx, waifusEmbed, DiscordUtils.divideFields(4, fields), toSend);
                    if (!toRemove.isEmpty()) {
                        for (String remove : toRemove) {
                            dbUser.getData().getWaifus().remove(remove);
                        }
                        player.saveAsync();
                    }
                }
            };
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("This command is the hub for all waifu operations. Yeah, it's all fiction.").setUsage("`~>waifu` - Shows a list of all your waifus and their current value.\n" + "`~>waifu [command] [@user]`").addParameterOptional("command", "The subcommand to use." + " Check the sub-command section for more information on which ones you can use.").addParameterOptional("@user", "The user you want to do the action with.").addParameterOptional("-id", "Shows the user id.").build();
        }
    });
    cr.registerAlias("waifu", "waifus");
    waifu.setPredicate(ctx -> RatelimitUtils.ratelimit(rl, ctx, false));
    waifu.addSubCommand("optout", new SubCommand() {

        @Override
        public String description() {
            return "Opt-out of the waifu stuff. This will disable the waifu system, remove all of your claims and make you unable to be claimed.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var player = ctx.getPlayer();
            if (player.getData().isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                return;
            }
            ctx.sendLocalized("commands.waifu.optout.warning", EmoteReference.WARNING);
            InteractiveOperations.create(ctx.getChannel(), ctx.getAuthor().getIdLong(), 60, e -> {
                if (!e.getAuthor().getId().equals(ctx.getAuthor().getId())) {
                    return Operation.IGNORED;
                }
                final var c = e.getMessage().getContentRaw();
                if (c.equalsIgnoreCase("Yes, I want to opt out of the waifu system completely and irreversibly")) {
                    player.getData().setWaifuout(true);
                    ctx.sendLocalized("commands.waifu.optout.success", EmoteReference.CORRECT);
                    player.saveUpdating();
                    return Operation.COMPLETED;
                } else if (c.equalsIgnoreCase("no")) {
                    ctx.sendLocalized("commands.waifu.optout.cancelled", EmoteReference.CORRECT);
                    return Operation.COMPLETED;
                }
                return Operation.IGNORED;
            });
        }
    });
    waifu.addSubCommand("stats", new SubCommand() {

        @Override
        public String description() {
            return "Shows your waifu stats or the stats or someone's (by mentioning them)";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var player = ctx.getPlayer();
            final var playerData = player.getData();
            if (playerData.isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                return;
            }
            if (!ctx.getSelfMember().hasPermission(ctx.getChannel(), Permission.MESSAGE_EMBED_LINKS)) {
                ctx.sendLocalized("general.missing_embed_permissions");
                return;
            }
            ctx.findMember(content, members -> {
                final var member = CustomFinderUtil.findMemberDefault(content, members, ctx, ctx.getMember());
                if (member == null)
                    return;
                final var toLookup = member.getUser();
                if (toLookup.isBot()) {
                    ctx.sendLocalized("commands.waifu.bot", EmoteReference.ERROR);
                    return;
                }
                final var waifuClaimed = ctx.getPlayer(toLookup);
                if (waifuClaimed.getData().isWaifuout()) {
                    ctx.sendLocalized("commands.waifu.optout.lookup_notice", EmoteReference.ERROR);
                    return;
                }
                final var waifuStats = calculateWaifuValue(waifuClaimed, toLookup);
                final var finalValue = waifuStats.getFinalValue();
                EmbedBuilder statsBuilder = new EmbedBuilder().setThumbnail(toLookup.getEffectiveAvatarUrl()).setAuthor(toLookup == ctx.getAuthor() ? languageContext.get("commands.waifu.stats.header") : languageContext.get("commands.waifu.stats.header_other").formatted(toLookup.getName()), null, toLookup.getEffectiveAvatarUrl()).setColor(Color.PINK).setDescription(languageContext.get("commands.waifu.stats.format").formatted(EmoteReference.BLUE_SMALL_MARKER, waifuStats.getMoneyValue(), waifuStats.getBadgeValue(), waifuStats.getExperienceValue(), waifuStats.getClaimValue(), waifuStats.getReputationMultiplier())).addField(EmoteReference.ZAP.toHeaderString() + languageContext.get("commands.waifu.stats.performance"), waifuStats.getPerformance() + "wp", true).addField(EmoteReference.MONEY.toHeaderString() + languageContext.get("commands.waifu.stats.value"), languageContext.get("commands.waifu.stats.credits").formatted(finalValue), false).setFooter(languageContext.get("commands.waifu.notice"), null);
                ctx.send(statsBuilder.build());
            });
        }
    });
    waifu.addSubCommand("claim", new SubCommand() {

        @Override
        public String description() {
            return "Claim a waifu. You need to mention the person you want to claim. Usage: `~>waifu claim <@mention>`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var player = ctx.getPlayer();
            if (player.getData().isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                return;
            }
            if (ctx.getMentionedUsers().isEmpty()) {
                ctx.sendLocalized("commands.waifu.claim.no_user", EmoteReference.ERROR);
                return;
            }
            final var toLookup = ctx.getMentionedUsers().get(0);
            if (toLookup.isBot()) {
                ctx.sendLocalized("commands.waifu.bot", EmoteReference.ERROR);
                return;
            }
            final var claimerPlayer = ctx.getPlayer();
            final var claimerPlayerData = claimerPlayer.getData();
            final var claimerUser = ctx.getDBUser();
            final var claimerUserData = claimerUser.getData();
            final var claimedPlayer = ctx.getPlayer(toLookup);
            final var claimedPlayerData = claimedPlayer.getData();
            final var claimedUser = ctx.getDBUser(toLookup);
            final var claimedUserData = claimedUser.getData();
            if (claimedPlayerData.isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.claim_notice", EmoteReference.ERROR);
                return;
            }
            // Waifu object declaration.
            final Waifu waifuToClaim = calculateWaifuValue(claimedPlayer, toLookup);
            final long waifuFinalValue = waifuToClaim.getFinalValue();
            // Checks.
            if (toLookup.getIdLong() == ctx.getAuthor().getIdLong()) {
                ctx.sendLocalized("commands.waifu.claim.yourself", EmoteReference.ERROR);
                return;
            }
            if (claimerUser.getData().getWaifus().entrySet().stream().anyMatch((w) -> w.getKey().equals(toLookup.getId()))) {
                ctx.sendLocalized("commands.waifu.claim.already_claimed", EmoteReference.ERROR);
                return;
            }
            // If the to-be claimed has the claim key in their inventory, it cannot be claimed.
            if (claimedPlayerData.isClaimLocked()) {
                ctx.sendLocalized("commands.waifu.claim.key_locked", EmoteReference.ERROR);
                return;
            }
            if (claimerPlayer.isLocked()) {
                ctx.sendLocalized("commands.waifu.claim.locked", EmoteReference.ERROR);
                return;
            }
            // Deduct from balance and checks for money.
            if (!claimerPlayer.removeMoney(waifuFinalValue)) {
                ctx.sendLocalized("commands.waifu.claim.not_enough_money", EmoteReference.ERROR, waifuFinalValue);
                return;
            }
            if (claimerUserData.getWaifus().size() >= claimerUserData.getWaifuSlots()) {
                ctx.sendLocalized("commands.waifu.claim.not_enough_slots", EmoteReference.ERROR, claimerUserData.getWaifuSlots(), claimerUserData.getWaifus().size());
                return;
            }
            if (waifuFinalValue > 100_000) {
                claimerPlayerData.addBadgeIfAbsent(Badge.GOLD_VALUE);
            }
            // Add waifu to claimer list.
            claimerUserData.getWaifus().put(toLookup.getId(), waifuFinalValue);
            claimedUserData.setTimesClaimed(claimedUserData.getTimesClaimed() + 1);
            boolean badgesAdded = false;
            // Add badges
            if (claimedUserData.getWaifus().containsKey(ctx.getAuthor().getId()) && claimerUserData.getWaifus().containsKey(toLookup.getId())) {
                claimerPlayerData.addBadgeIfAbsent(Badge.MUTUAL);
                badgesAdded = claimedPlayerData.addBadgeIfAbsent(Badge.MUTUAL);
            }
            claimerPlayerData.addBadgeIfAbsent(Badge.WAIFU_CLAIMER);
            if (badgesAdded || claimedPlayerData.addBadgeIfAbsent(Badge.CLAIMED)) {
                claimedPlayer.saveAsync();
            }
            // Massive saving operation owo.
            claimerPlayer.saveAsync();
            claimedUser.saveAsync();
            claimerUser.saveAsync();
            // Send confirmation message
            ctx.sendLocalized("commands.waifu.claim.success", EmoteReference.CORRECT, toLookup.getName(), waifuFinalValue, claimerUserData.getWaifus().size());
        }
    });
    waifu.addSubCommand("unclaim", new SubCommand() {

        @Override
        public String description() {
            return "Unclaims a waifu. You need to mention them, or you can also use their user id if they're not in any servers you share. Usage: `~>waifu unclaim <@mention>`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var optionalArguments = ctx.getOptionalArguments();
            content = Utils.replaceArguments(optionalArguments, content, "unknown");
            final var isId = content.matches("\\d{16,20}");
            final var player = ctx.getPlayer();
            if (player.getData().isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                return;
            }
            if (content.isEmpty() && !isId) {
                ctx.sendLocalized("commands.waifu.unclaim.no_user", EmoteReference.ERROR);
                return;
            }
            // This is hacky as heck, but assures us we get an empty result on id lookup.
            final var lookup = isId ? "" : content;
            // Lambdas strike again.
            final var finalContent = content;
            ctx.findMember(lookup, members -> {
                // This is hacky again, but search *will* fail if we pass a empty list to this method.
                final var member = isId ? null : CustomFinderUtil.findMember(lookup, members, ctx);
                if (member == null && !isId) {
                    return;
                }
                final var toLookup = isId ? ctx.retrieveUserById(finalContent) : member.getUser();
                final var isUnknown = isId && optionalArguments.containsKey("unknown") && toLookup == null;
                if (toLookup == null && !isUnknown) {
                    ctx.sendLocalized("commands.waifu.unclaim.not_found", EmoteReference.ERROR);
                    return;
                }
                // It'll only be null if -unknown is passed with an unknown ID. This is unclaim, so this check is a bit irrelevant though.
                if (!isUnknown && toLookup.isBot()) {
                    ctx.sendLocalized("commands.waifu.bot", EmoteReference.ERROR);
                    return;
                }
                final var userId = isUnknown ? finalContent : toLookup.getId();
                final var name = isUnknown ? "Unknown User" : toLookup.getName();
                final var claimerUser = ctx.getDBUser();
                final var data = claimerUser.getData();
                final var value = data.getWaifus().get(userId);
                if (value == null) {
                    ctx.sendLocalized("commands.waifu.not_claimed", EmoteReference.ERROR);
                    return;
                }
                final var claimedPlayer = ctx.getPlayer(toLookup);
                final var currentValue = calculateWaifuValue(claimedPlayer, toLookup).getFinalValue();
                final var valuePayment = (long) (currentValue * 0.15);
                // Send confirmation message.
                ctx.sendLocalized("commands.waifu.unclaim.confirmation", EmoteReference.MEGA, name, valuePayment, EmoteReference.STOPWATCH);
                InteractiveOperations.create(ctx.getChannel(), ctx.getAuthor().getIdLong(), 60, (ie) -> {
                    if (!ie.getAuthor().getId().equals(ctx.getAuthor().getId())) {
                        return Operation.IGNORED;
                    }
                    // Replace prefix because people seem to think you have to add the prefix before saying yes.
                    var ctn = ie.getMessage().getContentRaw();
                    for (var s : ctx.getConfig().prefix) {
                        if (ctn.toLowerCase().startsWith(s)) {
                            ctn = ctn.substring(s.length());
                        }
                    }
                    final var guildCustomPrefix = ctx.getDBGuild().getData().getGuildCustomPrefix();
                    if (guildCustomPrefix != null && !guildCustomPrefix.isEmpty() && ctn.toLowerCase().startsWith(guildCustomPrefix)) {
                        ctn = ctn.substring(guildCustomPrefix.length());
                    }
                    if (ctn.equalsIgnoreCase("yes")) {
                        final var p = ctx.getPlayer();
                        final var user = ctx.getDBUser();
                        final var userData = user.getData();
                        if (p.getCurrentMoney() < valuePayment) {
                            ctx.sendLocalized("commands.waifu.unclaim.not_enough_money", EmoteReference.ERROR);
                            return Operation.COMPLETED;
                        }
                        if (p.isLocked()) {
                            ctx.sendLocalized("commands.waifu.unclaim.player_locked", EmoteReference.ERROR);
                            return Operation.COMPLETED;
                        }
                        p.removeMoney(valuePayment);
                        userData.getWaifus().remove(userId);
                        user.save();
                        p.save();
                        ctx.sendLocalized("commands.waifu.unclaim.success", EmoteReference.CORRECT, name, valuePayment);
                        return Operation.COMPLETED;
                    } else if (ctn.equalsIgnoreCase("no")) {
                        ctx.sendLocalized("commands.waifu.unclaim.scrapped", EmoteReference.CORRECT);
                        return Operation.COMPLETED;
                    }
                    return Operation.IGNORED;
                });
            });
        }
    });
    waifu.addSubCommand("buyslot", new SubCommand() {

        @Override
        public String description() {
            return "Buys a new waifu slot. Maximum slots are 30, costs get increasingly higher.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var baseValue = 3000;
            final var user = ctx.getDBUser();
            final var player = ctx.getPlayer();
            final var userData = user.getData();
            if (player.getData().isWaifuout()) {
                ctx.sendLocalized("commands.waifu.optout.notice", EmoteReference.ERROR);
                return;
            }
            final var currentSlots = userData.getWaifuSlots();
            final var baseMultiplier = (currentSlots / 3) + 1;
            final var finalValue = baseValue * baseMultiplier;
            if (player.isLocked()) {
                ctx.sendLocalized("commands.waifu.buyslot.locked", EmoteReference.ERROR);
                return;
            }
            if (player.getCurrentMoney() < finalValue) {
                ctx.sendLocalized("commands.waifu.buyslot.not_enough_money", EmoteReference.ERROR, finalValue);
                return;
            }
            if (userData.getWaifuSlots() >= 30) {
                ctx.sendLocalized("commands.waifu.buyslot.too_many", EmoteReference.ERROR);
                return;
            }
            player.removeMoney(finalValue);
            userData.setWaifuSlots(currentSlots + 1);
            user.save();
            player.save();
            ctx.sendLocalized("commands.waifu.buyslot.success", EmoteReference.CORRECT, finalValue, userData.getWaifuSlots(), (userData.getWaifuSlots() - userData.getWaifus().size()));
        }
    });
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Badge(net.kodehawa.mantarobot.commands.currency.profile.Badge) Color(java.awt.Color) Module(net.kodehawa.mantarobot.core.modules.Module) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) Permission(net.dv8tion.jda.api.Permission) Utils(net.kodehawa.mantarobot.utils.Utils) User(net.dv8tion.jda.api.entities.User) ArrayList(java.util.ArrayList) CustomFinderUtil(net.kodehawa.mantarobot.utils.commands.CustomFinderUtil) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) Subscribe(com.google.common.eventbus.Subscribe) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) LinkedList(java.util.LinkedList) DiscordUtils(net.kodehawa.mantarobot.utils.commands.DiscordUtils) Player(net.kodehawa.mantarobot.db.entities.Player) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) InteractiveOperations(net.kodehawa.mantarobot.core.listeners.operations.InteractiveOperations) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Waifu(net.kodehawa.mantarobot.commands.currency.Waifu) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) Operation(net.kodehawa.mantarobot.core.listeners.operations.core.Operation) Player(net.kodehawa.mantarobot.db.entities.Player) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) User(net.dv8tion.jda.api.entities.User) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) Waifu(net.kodehawa.mantarobot.commands.currency.Waifu) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Subscribe(com.google.common.eventbus.Subscribe)

Example 2 with IncreasingRateLimiter

use of net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter in project MantaroBot by Mantaro.

the class LeaderboardCmd method richest.

@Subscribe
public void richest(CommandRegistry cr) {
    final IncreasingRateLimiter rateLimiter = new IncreasingRateLimiter.Builder().spamTolerance(3).limit(1).cooldown(2, TimeUnit.SECONDS).cooldownPenaltyIncrease(20, TimeUnit.SECONDS).maxCooldown(5, TimeUnit.MINUTES).pool(MantaroData.getDefaultJedisPool()).prefix("leaderboard").build();
    SimpleTreeCommand leaderboards = cr.register("leaderboard", new SimpleTreeCommand(CommandCategory.CURRENCY) {

        @Override
        public Command defaultTrigger(Context ctx, String mainCommand, String commandName) {
            ctx.sendLocalized("commands.leaderboard.main_page_redirect", EmoteReference.PENCIL);
            return null;
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Returns the currency leaderboard. See subcommands for the available leaderboards.").build();
        }
    });
    leaderboards.setPredicate(ctx -> {
        if (!ctx.getSelfMember().hasPermission(ctx.getChannel(), Permission.MESSAGE_EMBED_LINKS)) {
            ctx.sendLocalized("general.missing_embed_permissions");
            return false;
        }
        return RatelimitUtils.ratelimit(rateLimiter, ctx, null);
    });
    leaderboards.addSubCommand("gamble", new SubCommand() {

        @Override
        public String description() {
            return "Returns the gamble (times) leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var gambleLeaderboard = getLeaderboard("playerstats", "gambleWins", player -> player.pluck("id", "gambleWins"));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.gamble").formatted(EmoteReference.MONEY), "commands.leaderboard.gamble", gambleLeaderboard, map -> Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), map.get("gambleWins").toString()), "%s**%s#%s** - %,d", false).build());
        }
    });
    leaderboards.addSubCommand("slots", new SubCommand() {

        @Override
        public String description() {
            return "Returns the slots (times) leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var slotsLeaderboard = getLeaderboard("playerstats", "slotsWins", player -> player.pluck("id", "slotsWins"));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.slots").formatted(EmoteReference.MONEY), "commands.leaderboard.slots", slotsLeaderboard, map -> Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), map.get("slotsWins").toString()), "%s**%s#%s** - %,d", false).build());
        }
    });
    if (!config.isPremiumBot) {
        leaderboards.addSubCommand("money", new SubCommand() {

            @Override
            public String description() {
                return "Returns the money leaderboard";
            }

            @Override
            @SuppressWarnings("unchecked")
            protected void call(Context ctx, I18nContext languageContext, String content) {
                var seasonal = ctx.isSeasonal();
                var tableName = seasonal ? "seasonalplayers" : "players";
                var indexName = seasonal ? "money" : "newMoney";
                var moneyLeaderboard = getLeaderboard(tableName, indexName, player -> player.g("id"), player -> {
                    if (seasonal) {
                        return player.pluck("id", "money");
                    } else {
                        return player.pluck("id", "newMoney", r.hashMap("data", "newMoney"));
                    }
                });
                send(ctx, generateLeaderboardEmbed(ctx, seasonal ? languageContext.get("commands.leaderboard.inner.seasonal_money").formatted(EmoteReference.MONEY) : languageContext.get("commands.leaderboard.inner.money").formatted(EmoteReference.MONEY), "commands.leaderboard.money", moneyLeaderboard, map -> {
                    Object money;
                    if (seasonal) {
                        money = map.get("money");
                    } else {
                        money = ((Map<String, Object>) map.get("data")).get("newMoney");
                    }
                    return Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), money.toString());
                }, "%s**%s#%s** - $%,d", seasonal).build());
            }
        });
    }
    leaderboards.addSubCommand(config.isPremiumBot ? "money" : "oldmoney", new SubCommand() {

        @Override
        public String description() {
            if (config.isPremiumBot) {
                return "Returns the money leaderboard";
            } else {
                return "Returns the (old) pre-reset money leaderboard";
            }
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var tableName = "players";
            var moneyLeaderboard = getLeaderboard(tableName, "money", player -> player.g("id"), player -> player.pluck("id", "money"));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.money_old").formatted(EmoteReference.MONEY), "commands.leaderboard.money", moneyLeaderboard, map -> Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), map.get("money").toString()), "%s**%s#%s** - $%,d", false).build());
        }
    });
    leaderboards.addSubCommand("lvl", new SubCommand() {

        @Override
        public String description() {
            return "Returns the level leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var levelLeaderboard = getLeaderboard("players", "level", player -> player.g("id"), player -> player.pluck("id", "level", r.hashMap("data", "experience")));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.lvl").formatted(EmoteReference.ZAP), "commands.leaderboard.level", levelLeaderboard, map -> {
                @SuppressWarnings("unchecked") var experience = ((Map<String, Object>) map.get("data")).get("experience");
                return Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), map.get("level").toString() + "\n -" + languageContext.get("commands.leaderboard.inner.experience") + ":** " + experience + "**");
            }, "%s**%s#%s** - %s", false).build());
        }
    });
    leaderboards.addSubCommand("rep", new SubCommand() {

        @Override
        public String description() {
            return "Returns the reputation leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var seasonal = ctx.isSeasonal();
            var tableName = seasonal ? "seasonalplayers" : "players";
            var reputationLeaderboard = getLeaderboard(tableName, "reputation", player -> player.g("id"), player -> player.pluck("id", "reputation"));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.rep").formatted(EmoteReference.REP), "commands.leaderboard.reputation", reputationLeaderboard, map -> Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), map.get("reputation").toString()), "%s**%s#%s** - %,d", seasonal).build());
        }
    });
    leaderboards.addSubCommand("streak", new SubCommand() {

        @Override
        public String description() {
            return "Returns the daily streak leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var dailyLeaderboard = getLeaderboard("players", "userDailyStreak", player -> player.g("id"), player -> player.pluck("id", r.hashMap("data", "dailyStrike")));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.streak").formatted(EmoteReference.POPPER), "commands.leaderboard.daily", dailyLeaderboard, map -> {
                @SuppressWarnings("unchecked") var strike = ((Map<String, Object>) (map.get("data"))).get("dailyStrike").toString();
                return Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), strike);
            }, "%s**%s#%s** - %sx", false).build());
        }
    });
    leaderboards.addSubCommand("claim", new SubCommand() {

        @Override
        public String description() {
            return "Returns the waifu claim leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            List<Map<String, Object>> claimLeaderboard = getLeaderboard("users", "timesClaimed", player -> player.pluck("id", r.hashMap("data", "timesClaimed")));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.claim").formatted(EmoteReference.HEART), "commands.leaderboard.claim", claimLeaderboard, map -> {
                @SuppressWarnings("unchecked") var timesClaimed = ((Map<String, Object>) (map.get("data"))).get("timesClaimed").toString();
                return Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), timesClaimed);
            }, "%s**%s#%s** - %,d", false).build());
        }
    });
    leaderboards.addSubCommand("games", new SubCommand() {

        @Override
        public String description() {
            return "Returns the games wins leaderboard";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var seasonal = ctx.isSeasonal();
            var tableName = seasonal ? "seasonalplayers" : "players";
            List<Map<String, Object>> gameLeaderboard = getLeaderboard(tableName, "gameWins", player -> player.g("id"), player -> player.pluck("id", r.hashMap("data", "gamesWon")));
            send(ctx, generateLeaderboardEmbed(ctx, languageContext.get("commands.leaderboard.inner.game").formatted(EmoteReference.ZAP), "commands.leaderboard.game", gameLeaderboard, map -> {
                @SuppressWarnings("unchecked") var gamesWon = ((Map<String, Object>) (map.get("data"))).get("gamesWon").toString();
                return Pair.of(getMember(ctx, map.get("id").toString().split(":")[0]), gamesWon);
            }, "%s**%s#%s** - %,d", seasonal).build());
        }
    });
    leaderboards.createSubCommandAlias("rep", "reputation");
    leaderboards.createSubCommandAlias("lvl", "level");
    leaderboards.createSubCommandAlias("streak", "daily");
    leaderboards.createSubCommandAlias("games", "wins");
    cr.registerAlias("leaderboard", "richest");
    cr.registerAlias("leaderboard", "top");
    cr.registerAlias("leaderboard", "lb");
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Badge(net.kodehawa.mantarobot.commands.currency.profile.Badge) ReqlFunction1(com.rethinkdb.gen.ast.ReqlFunction1) Module(net.kodehawa.mantarobot.core.modules.Module) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) SimpleTreeCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleTreeCommand) Permission(net.dv8tion.jda.api.Permission) Utils(net.kodehawa.mantarobot.utils.Utils) Types(com.rethinkdb.utils.Types) StringUtils(org.apache.commons.lang3.StringUtils) Function(java.util.function.Function) RethinkDB.r(com.rethinkdb.RethinkDB.r) Pair(org.apache.commons.lang3.tuple.Pair) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) OptArgs(com.rethinkdb.model.OptArgs) Button(net.dv8tion.jda.api.interactions.components.Button) Map(java.util.Map) Subscribe(com.google.common.eventbus.Subscribe) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) Config(net.kodehawa.mantarobot.data.Config) Connection(com.rethinkdb.net.Connection) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) CachedLeaderboardMember(net.kodehawa.mantarobot.commands.utils.leaderboards.CachedLeaderboardMember) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) JsonDataManager(net.kodehawa.mantarobot.utils.data.JsonDataManager) Jedis(redis.clients.jedis.Jedis) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) SimpleTreeCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleTreeCommand) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) SimpleTreeCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleTreeCommand) List(java.util.List) Map(java.util.Map) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Subscribe(com.google.common.eventbus.Subscribe)

Example 3 with IncreasingRateLimiter

use of net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter in project MantaroBot by Mantaro.

the class PlayerCmds method rep.

@Subscribe
public void rep(CommandRegistry cr) {
    cr.register("rep", new SimpleCommand(CommandCategory.CURRENCY) {

        final IncreasingRateLimiter rateLimiter = new IncreasingRateLimiter.Builder().limit(1).cooldown(12, TimeUnit.HOURS).maxCooldown(12, TimeUnit.HOURS).pool(MantaroData.getDefaultJedisPool()).randomIncrement(false).prefix("rep").build();

        @Override
        public void call(Context ctx, String content, String[] args) {
            var rl = rateLimiter.getRemaniningCooldown(ctx.getAuthor());
            var languageContext = ctx.getLanguageContext();
            if (content.isEmpty()) {
                ctx.send(String.format(languageContext.get("commands.rep.no_mentions"), EmoteReference.ERROR, (rl > 0 ? String.format(languageContext.get("commands.rep.cooldown.waiting"), Utils.formatDuration(languageContext, rl)) : languageContext.get("commands.rep.cooldown.pass"))));
                return;
            }
            var mentioned = ctx.getMentionedUsers();
            if (!mentioned.isEmpty() && mentioned.size() > 1) {
                ctx.sendLocalized("commands.rep.more_than_one", EmoteReference.ERROR);
                return;
            }
            ctx.findMember(content, members -> {
                var member = CustomFinderUtil.findMember(content, members, ctx);
                if (member == null) {
                    return;
                }
                var usr = member.getUser();
                var author = ctx.getAuthor();
                Predicate<User> oldEnough = (u -> u.getTimeCreated().isBefore(OffsetDateTime.now().minus(30, ChronoUnit.DAYS)));
                // Didn't want to repeat the code twice, lol.
                if (!oldEnough.test(usr)) {
                    ctx.sendLocalized("commands.rep.new_account_notice", EmoteReference.ERROR);
                    return;
                }
                if (!oldEnough.test(author)) {
                    ctx.sendLocalized("commands.rep.new_account_notice", EmoteReference.ERROR);
                    return;
                }
                if (usr.isBot()) {
                    ctx.send(String.format(languageContext.get("commands.rep.rep_bot"), EmoteReference.THINKING, (rl > 0 ? String.format(languageContext.get("commands.rep.cooldown.waiting"), Utils.formatDuration(languageContext, rl)) : languageContext.get("commands.rep.cooldown.pass"))));
                    return;
                }
                if (usr.equals(ctx.getAuthor())) {
                    ctx.send(String.format(languageContext.get("commands.rep.rep_yourself"), EmoteReference.THINKING, (rl > 0 ? String.format(languageContext.get("commands.rep.cooldown.waiting"), Utils.formatDuration(languageContext, rl)) : languageContext.get("commands.rep.cooldown.pass"))));
                    return;
                }
                if (ctx.isUserBlacklisted(usr.getId())) {
                    ctx.sendLocalized("commands.rep.blacklisted_rep", EmoteReference.ERROR);
                    return;
                }
                if (!RatelimitUtils.ratelimit(rateLimiter, ctx, languageContext.get("commands.rep.cooldown.explanation"), false)) {
                    return;
                }
                var player = UnifiedPlayer.of(usr, ctx.getConfig().getCurrentSeason());
                player.addReputation(1L);
                player.saveUpdating();
                ctx.sendStrippedLocalized("commands.rep.success", EmoteReference.CORRECT, member.getEffectiveName());
            });
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Gives 1 reputation to an user").setUsage("`~>rep <@user>` - Gives reputation to x user\n" + "This command is only usable every 12 hours").addParameter("@user", "User to mention").build();
        }
    });
    cr.registerAlias("rep", "reputation");
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Badge(net.kodehawa.mantarobot.commands.currency.profile.Badge) Color(java.awt.Color) Module(net.kodehawa.mantarobot.core.modules.Module) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) PlayerData(net.kodehawa.mantarobot.db.entities.helpers.PlayerData) Utils(net.kodehawa.mantarobot.utils.Utils) Random(java.util.Random) User(net.dv8tion.jda.api.entities.User) InteractiveOperation(net.kodehawa.mantarobot.core.listeners.operations.core.InteractiveOperation) CustomFinderUtil(net.kodehawa.mantarobot.utils.commands.CustomFinderUtil) ITreeCommand(net.kodehawa.mantarobot.core.modules.commands.base.ITreeCommand) PlayerEquipment(net.kodehawa.mantarobot.commands.currency.item.PlayerEquipment) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) DBUser(net.kodehawa.mantarobot.db.entities.DBUser) Subscribe(com.google.common.eventbus.Subscribe) SimpleCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleCommand) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) LinkedList(java.util.LinkedList) ItemHelper(net.kodehawa.mantarobot.commands.currency.item.ItemHelper) ItemStack(net.kodehawa.mantarobot.commands.currency.item.ItemStack) DiscordUtils(net.kodehawa.mantarobot.utils.commands.DiscordUtils) Player(net.kodehawa.mantarobot.db.entities.Player) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) ItemReference(net.kodehawa.mantarobot.commands.currency.item.ItemReference) InteractiveOperations(net.kodehawa.mantarobot.core.listeners.operations.InteractiveOperations) Predicate(java.util.function.Predicate) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) UnifiedPlayer(net.kodehawa.mantarobot.commands.currency.seasons.helpers.UnifiedPlayer) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Collectors(java.util.stream.Collectors) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) TimeUnit(java.util.concurrent.TimeUnit) Breakable(net.kodehawa.mantarobot.commands.currency.item.special.helpers.Breakable) List(java.util.List) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) OffsetDateTime(java.time.OffsetDateTime) ChronoUnit(java.time.temporal.ChronoUnit) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) Collections(java.util.Collections) SimpleCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleCommand) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) Predicate(java.util.function.Predicate) Subscribe(com.google.common.eventbus.Subscribe)

Example 4 with IncreasingRateLimiter

use of net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter in project MantaroBot by Mantaro.

the class MoneyCmds method loot.

@Subscribe
public void loot(CommandRegistry cr) {
    final IncreasingRateLimiter rateLimiter = new IncreasingRateLimiter.Builder().limit(1).spamTolerance(2).cooldown(3, TimeUnit.MINUTES).maxCooldown(3, TimeUnit.MINUTES).randomIncrement(false).premiumAware(true).pool(MantaroData.getDefaultJedisPool()).prefix("loot").build();
    final ZoneId zoneId = ZoneId.systemDefault();
    final SecureRandom random = new SecureRandom();
    cr.register("loot", new SimpleCommand(CommandCategory.CURRENCY) {

        @Override
        public void call(Context ctx, String content, String[] args) {
            var unifiedPlayer = UnifiedPlayer.of(ctx.getAuthor(), ctx.getConfig().getCurrentSeason());
            var player = unifiedPlayer.getPlayer();
            var playerData = player.getData();
            var dbUser = ctx.getDBUser();
            var languageContext = ctx.getLanguageContext();
            if (player.isLocked()) {
                ctx.sendLocalized("commands.loot.player_locked", EmoteReference.ERROR);
                return;
            }
            if (!RatelimitUtils.ratelimit(rateLimiter, ctx)) {
                return;
            }
            var today = LocalDate.now(zoneId);
            var eventStart = today.withMonth(Month.DECEMBER.getValue()).withDayOfMonth(23);
            // Up to the 25th
            var eventStop = eventStart.plusDays(3);
            var ground = TextChannelGround.of(ctx.getEvent());
            if (today.isEqual(eventStart) || (today.isAfter(eventStart) && today.isBefore(eventStop))) {
                ground.dropItemWithChance(ItemReference.CHRISTMAS_TREE_SPECIAL, 4);
                ground.dropItemWithChance(ItemReference.BELL_SPECIAL, 4);
            }
            if (random.nextInt(100) > 95) {
                ground.dropItem(ItemReference.LOOT_CRATE);
                if (playerData.addBadgeIfAbsent(Badge.LUCKY)) {
                    player.saveUpdating();
                }
            }
            var loot = ground.collectItems();
            var moneyFound = ground.collectMoney() + Math.max(0, random.nextInt(70));
            // Make the credits minimum 10, instead of... 1
            if (moneyFound != 0) {
                moneyFound = Math.max(10, moneyFound);
            }
            if (dbUser.isPremium() && moneyFound > 0) {
                int extra = (int) (moneyFound * 1.5);
                moneyFound += random.nextInt(extra);
            }
            var extraMessage = "";
            // Sellout
            if (playerData.shouldSeeCampaign()) {
                extraMessage += Campaign.PREMIUM.getStringFromCampaign(languageContext, dbUser.isPremium());
                playerData.markCampaignAsSeen();
            }
            if (!loot.isEmpty()) {
                var stack = ItemStack.toString(ItemStack.reduce(loot));
                if (player.getInventory().merge(loot))
                    extraMessage += languageContext.withRoot("commands", "loot.item_overflow");
                if (moneyFound != 0) {
                    if (unifiedPlayer.addMoney(moneyFound)) {
                        ctx.sendLocalized("commands.loot.with_item.found", EmoteReference.POPPER, stack, moneyFound, extraMessage);
                    } else {
                        ctx.sendLocalized("commands.loot.with_item.found_but_overflow", EmoteReference.POPPER, stack, moneyFound, extraMessage);
                    }
                } else {
                    ctx.sendLocalized("commands.loot.with_item.found_only_item_but_overflow", EmoteReference.MEGA, stack, extraMessage);
                }
            } else {
                if (moneyFound != 0) {
                    if (unifiedPlayer.addMoney(moneyFound)) {
                        ctx.sendLocalized("commands.loot.without_item.found", EmoteReference.POPPER, moneyFound, extraMessage);
                    } else {
                        ctx.sendLocalized("commands.loot.without_item.found_but_overflow", EmoteReference.POPPER, moneyFound);
                    }
                } else {
                    var dust = dbUser.getData().increaseDustLevel(random.nextInt(2));
                    var msg = languageContext.withRoot("commands", "loot.dust").formatted(dust);
                    dbUser.save();
                    if (random.nextInt(100) > 93) {
                        msg += languageContext.withRoot("commands", "loot.easter");
                    }
                    ctx.send(EmoteReference.SAD + msg);
                }
            }
            unifiedPlayer.saveUpdating();
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Loot the current chat for items, for usage in Mantaro's currency system. " + "You have a random chance of getting collectible items from here.").build();
        }
    });
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) ZoneId(java.time.ZoneId) SimpleCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleCommand) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) SecureRandom(java.security.SecureRandom) Subscribe(com.google.common.eventbus.Subscribe)

Example 5 with IncreasingRateLimiter

use of net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter in project MantaroBot by Mantaro.

the class MarryCmd method marry.

@Subscribe
public void marry(CommandRegistry cr) {
    final IncreasingRateLimiter rateLimiter = new IncreasingRateLimiter.Builder().limit(1).cooldown(10, TimeUnit.MINUTES).maxCooldown(40, TimeUnit.MINUTES).randomIncrement(false).pool(MantaroData.getDefaultJedisPool()).prefix("marry").build();
    ITreeCommand marryCommand = cr.register("marry", new TreeCommand(CommandCategory.CURRENCY) {

        @Override
        public Command defaultTrigger(Context ctx, String mainCommand, String commandName) {
            return new SubCommand() {

                @Override
                protected void call(Context ctx, I18nContext languageContext, String content) {
                    if (ctx.getMentionedUsers().isEmpty()) {
                        ctx.sendLocalized("commands.marry.no_mention", EmoteReference.ERROR);
                        return;
                    }
                    // We don't need to change those. I sure fucking hope we don't.
                    final DBGuild dbGuild = ctx.getDBGuild();
                    User proposingUser = ctx.getAuthor();
                    User proposedToUser = ctx.getMentionedUsers().get(0);
                    // This is just for checking purposes, so we don't need the DBUser itself.
                    UserData proposingUserData = ctx.getDBUser(proposingUser).getData();
                    UserData proposedToUserData = ctx.getDBUser(proposedToUser).getData();
                    // Again just for checking, and no need to change.
                    final Inventory proposingPlayerInventory = ctx.getPlayer(proposingUser).getInventory();
                    // Why would you do this...
                    if (proposedToUser.getId().equals(ctx.getAuthor().getId())) {
                        ctx.sendLocalized("commands.marry.marry_yourself_notice", EmoteReference.ERROR);
                        return;
                    }
                    final Marriage proposingMarriage = proposingUserData.getMarriage();
                    final Marriage proposedToMarriage = proposedToUserData.getMarriage();
                    // Proposed to is a bot user, cannot marry bots, this is still not 2100.
                    if (proposedToUser.isBot()) {
                        ctx.sendLocalized("commands.marry.marry_bot_notice", EmoteReference.ERROR);
                        return;
                    }
                    // Already married to the same person you're proposing to.
                    if ((proposingMarriage != null && proposedToMarriage != null) && proposedToUserData.getMarriage().getId().equals(proposingMarriage.getId())) {
                        ctx.sendLocalized("commands.marry.already_married_receipt", EmoteReference.ERROR);
                        return;
                    }
                    // You're already married. Huh huh.
                    if (proposingMarriage != null) {
                        ctx.sendLocalized("commands.marry.already_married", EmoteReference.ERROR);
                        return;
                    }
                    // Receipt is married, cannot continue.
                    if (proposedToMarriage != null) {
                        ctx.sendLocalized("commands.marry.receipt_married", EmoteReference.ERROR);
                        return;
                    }
                    // Not enough rings to continue. Buy more rings w.
                    if (!proposingPlayerInventory.containsItem(ItemReference.RING) || proposingPlayerInventory.getAmount(ItemReference.RING) < 2) {
                        ctx.sendLocalized("commands.marry.no_ring", EmoteReference.ERROR);
                        return;
                    }
                    // Check for rate limit
                    if (!RatelimitUtils.ratelimit(rateLimiter, ctx, ctx.getLanguageContext().get("commands.marry.ratelimit_message"), false))
                        return;
                    // Send confirmation message.
                    ctx.sendLocalized("commands.marry.confirmation", EmoteReference.MEGA, proposedToUser.getName(), ctx.getAuthor().getName(), EmoteReference.STOPWATCH);
                    InteractiveOperations.create(ctx.getChannel(), ctx.getAuthor().getIdLong(), 120, (ie) -> {
                        // Ignore all messages from anyone that isn't the user we already proposed to. Waiting for confirmation...
                        if (!ie.getAuthor().getId().equals(proposedToUser.getId()))
                            return Operation.IGNORED;
                        // Replace prefix because people seem to think you have to add the prefix before saying yes.
                        String message = ie.getMessage().getContentRaw();
                        for (String s : ctx.getConfig().prefix) {
                            if (message.toLowerCase().startsWith(s)) {
                                message = message.substring(s.length());
                            }
                        }
                        String guildCustomPrefix = dbGuild.getData().getGuildCustomPrefix();
                        if (guildCustomPrefix != null && !guildCustomPrefix.isEmpty() && message.toLowerCase().startsWith(guildCustomPrefix)) {
                            message = message.substring(guildCustomPrefix.length());
                        }
                        // Lovely~ <3
                        if (message.equalsIgnoreCase("yes")) {
                            // Here we NEED to get the Player,
                            // User and Marriage objects once again
                            // to avoid race conditions or changes on those that might have happened on the 120 seconds that this lasted for.
                            // We need to check if the marriage is empty once again before continuing, also if we have enough rings!
                            // Else we end up with really annoying to debug bugs, lol.
                            Player proposingPlayer = ctx.getPlayer(proposingUser);
                            Player proposedToPlayer = ctx.getPlayer(proposedToUser);
                            DBUser proposingUserDB = ctx.getDBUser(proposingUser);
                            DBUser proposedToUserDB = ctx.getDBUser(proposedToUser);
                            final Marriage proposingMarriageFinal = proposingUserDB.getData().getMarriage();
                            final Marriage proposedToMarriageFinal = proposedToUserDB.getData().getMarriage();
                            if (proposingMarriageFinal != null) {
                                ctx.sendLocalized("commands.marry.already_married", EmoteReference.ERROR);
                                return Operation.COMPLETED;
                            }
                            if (proposedToMarriageFinal != null) {
                                ctx.sendLocalized("commands.marry.receipt_married", EmoteReference.ERROR);
                                return Operation.COMPLETED;
                            }
                            // LAST inventory check and ring assignment is gonna happen using those.
                            final Inventory proposingPlayerFinalInventory = proposingPlayer.getInventory();
                            final Inventory proposedToPlayerInventory = proposedToPlayer.getInventory();
                            if (proposingPlayerFinalInventory.getAmount(ItemReference.RING) < 2) {
                                ctx.sendLocalized("commands.marry.ring_check_fail", EmoteReference.ERROR);
                                return Operation.COMPLETED;
                            }
                            // Remove the ring from the proposing player inventory.
                            proposingPlayerFinalInventory.process(new ItemStack(ItemReference.RING, -1));
                            // Silently scrape the rings if the receipt has more than 5000 rings.
                            if (proposedToPlayerInventory.getAmount(ItemReference.RING) < 5000) {
                                proposedToPlayerInventory.process(new ItemStack(ItemReference.RING, 1));
                            }
                            final long marriageCreationMillis = Instant.now().toEpochMilli();
                            // Onto the UUID we need to encode userId + timestamp of
                            // the proposing player and the proposed to player after the acceptance is done.
                            String marriageId = new UUID(proposingUser.getIdLong(), proposedToUser.getIdLong()).toString();
                            // Make and save the new marriage object.
                            Marriage actualMarriage = Marriage.of(marriageId, proposingUser, proposedToUser);
                            actualMarriage.getData().setMarriageCreationMillis(marriageCreationMillis);
                            actualMarriage.save();
                            // Assign the marriage ID to the respective users and save it.
                            proposingUserDB.getData().setMarriageId(marriageId);
                            proposedToUserDB.getData().setMarriageId(marriageId);
                            proposingUserDB.save();
                            proposedToUserDB.save();
                            // Send marriage confirmation message.
                            ctx.sendLocalized("commands.marry.accepted", EmoteReference.POPPER, ie.getAuthor().getName(), ie.getAuthor().getDiscriminator(), proposingUser.getName(), proposingUser.getDiscriminator());
                            // Add the badge to the married couple.
                            proposingPlayer.getData().addBadgeIfAbsent(Badge.MARRIED);
                            proposedToPlayer.getData().addBadgeIfAbsent(Badge.MARRIED);
                            // Give a love letter both to the proposing player and the one who was proposed to.
                            if (proposingPlayerFinalInventory.getAmount(ItemReference.LOVE_LETTER) < 5000) {
                                proposingPlayerFinalInventory.process(new ItemStack(ItemReference.LOVE_LETTER, 1));
                            }
                            if (proposedToPlayerInventory.getAmount(ItemReference.LOVE_LETTER) < 5000) {
                                proposedToPlayerInventory.process(new ItemStack(ItemReference.LOVE_LETTER, 1));
                            }
                            // Badge assignment saving.
                            proposingPlayer.save();
                            proposedToPlayer.save();
                            return Operation.COMPLETED;
                        }
                        if (message.equalsIgnoreCase("no")) {
                            ctx.sendLocalized("commands.marry.denied", EmoteReference.CORRECT, proposingUser.getName());
                            // Well, we have a badge for this too. Consolation prize I guess.
                            final Player proposingPlayer = ctx.getPlayer(proposingUser);
                            if (proposingPlayer.getData().addBadgeIfAbsent(Badge.DENIED)) {
                                proposingPlayer.saveUpdating();
                            }
                            return Operation.COMPLETED;
                        }
                        return Operation.IGNORED;
                    });
                }
            };
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Basically marries you with a user.").setUsage("`~>marry <@mention>` - Propose to someone\n" + "`~>marry <command>`").addParameter("@mention", "The person to propose to").addParameter("command", "The subcommand you can use. Check the subcommands section for a list and usage of each.").build();
        }
    });
    marryCommand.addSubCommand("createletter", new SubCommand() {

        @Override
        public String description() {
            return "Create a love letter for your marriage. Usage: `~>marry createletter <content>`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final User author = ctx.getAuthor();
            Player player = ctx.getPlayer();
            Inventory playerInventory = player.getInventory();
            DBUser dbUser = ctx.getDBUser();
            // Without one love letter we cannot do much, ya know.
            if (playerInventory.containsItem(ItemReference.LOVE_LETTER)) {
                final Marriage currentMarriage = dbUser.getData().getMarriage();
                // that the love letter is less than 1500 characters long.
                if (currentMarriage == null) {
                    ctx.sendLocalized("commands.marry.loveletter.no_marriage", EmoteReference.SAD);
                    return;
                }
                if (currentMarriage.getData().getLoveLetter() != null) {
                    ctx.sendLocalized("commands.marry.loveletter.already_done", EmoteReference.ERROR);
                    return;
                }
                if (content.isEmpty()) {
                    ctx.sendLocalized("commands.marry.loveletter.empty", EmoteReference.ERROR);
                    return;
                }
                if (content.length() > 500) {
                    ctx.sendLocalized("commands.marry.loveletter.too_long", EmoteReference.ERROR);
                    return;
                }
                // Can we find the user this is married to?
                final User marriedTo = ctx.retrieveUserById(currentMarriage.getOtherPlayer(author.getId()));
                if (marriedTo == null) {
                    ctx.sendLocalized("commands.marry.loveletter.cannot_see", EmoteReference.ERROR);
                    return;
                }
                // Send a confirmation message.
                String finalContent = Utils.DISCORD_INVITE.matcher(content).replaceAll("-invite link-");
                finalContent = Utils.DISCORD_INVITE_2.matcher(finalContent).replaceAll("-invite link-");
                ctx.sendStrippedLocalized("commands.marry.loveletter.confirmation", EmoteReference.TALKING, marriedTo.getName(), marriedTo.getDiscriminator(), finalContent);
                // Start the operation.
                InteractiveOperations.create(ctx.getChannel(), author.getIdLong(), 60, e -> {
                    if (!e.getAuthor().getId().equals(author.getId())) {
                        return Operation.IGNORED;
                    }
                    // Replace prefix because people seem to think you have to add the prefix before saying yes.
                    String c = e.getMessage().getContentRaw();
                    for (String s : ctx.getConfig().prefix) {
                        if (c.toLowerCase().startsWith(s)) {
                            c = c.substring(s.length());
                        }
                    }
                    String guildCustomPrefix = ctx.getDBGuild().getData().getGuildCustomPrefix();
                    if (guildCustomPrefix != null && !guildCustomPrefix.isEmpty() && c.toLowerCase().startsWith(guildCustomPrefix)) {
                        c = c.substring(guildCustomPrefix.length());
                    }
                    // Confirmed they want to save this as the permanent love letter.
                    if (c.equalsIgnoreCase("yes")) {
                        final Player playerFinal = ctx.getPlayer();
                        final Inventory inventoryFinal = playerFinal.getInventory();
                        final Marriage currentMarriageFinal = dbUser.getData().getMarriage();
                        // We need to do most of the checks all over again just to make sure nothing important slipped through.
                        if (currentMarriageFinal == null) {
                            ctx.sendLocalized("commands.marry.loveletter.no_marriage", EmoteReference.SAD);
                            return Operation.COMPLETED;
                        }
                        if (!inventoryFinal.containsItem(ItemReference.LOVE_LETTER)) {
                            ctx.sendLocalized("commands.marry.loveletter.no_letter", EmoteReference.SAD);
                            return Operation.COMPLETED;
                        }
                        // Remove the love letter from the inventory.
                        inventoryFinal.process(new ItemStack(ItemReference.LOVE_LETTER, -1));
                        playerFinal.save();
                        // Save the love letter. The content variable is the actual letter, while c is the content of the operation itself.
                        // Yes it's confusing.
                        currentMarriageFinal.getData().setLoveLetter(content);
                        currentMarriageFinal.save();
                        ctx.sendLocalized("commands.marry.loveletter.confirmed", EmoteReference.CORRECT);
                        return Operation.COMPLETED;
                    } else if (c.equalsIgnoreCase("no")) {
                        ctx.sendLocalized("commands.marry.loveletter.scrapped", EmoteReference.CORRECT);
                        return Operation.COMPLETED;
                    }
                    return Operation.IGNORED;
                });
            } else {
                ctx.sendLocalized("commands.marry.loveletter.no_letter", EmoteReference.SAD);
            }
        }
    });
    marryCommand.addSubCommand("house", new SubCommand() {

        @Override
        public String description() {
            return "Buys a house to live in. You need to buy a house in market first. Usage: `~>marry buyhouse <name>`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var player = ctx.getPlayer();
            var playerInventory = player.getInventory();
            var dbUser = ctx.getDBUser();
            var marriage = dbUser.getData().getMarriage();
            if (marriage == null) {
                ctx.sendLocalized("commands.marry.buyhouse.not_married", EmoteReference.ERROR);
                return;
            }
            if (!playerInventory.containsItem(ItemReference.HOUSE)) {
                ctx.sendLocalized("commands.marry.buyhouse.no_house", EmoteReference.ERROR);
                return;
            }
            if (player.getCurrentMoney() < housePrice) {
                ctx.sendLocalized("commands.marry.buyhouse.not_enough_money", EmoteReference.ERROR, housePrice);
                return;
            }
            content = content.replace("\n", "").trim();
            if (content.isEmpty()) {
                ctx.sendLocalized("commands.marry.buyhouse.no_name", EmoteReference.ERROR);
                return;
            }
            if (content.length() > 150) {
                ctx.sendLocalized("commands.pet.buy.too_long", EmoteReference.ERROR);
                return;
            }
            var finalContent = Utils.HTTP_URL.matcher(content).replaceAll("-url-");
            ctx.sendLocalized("commands.marry.buyhouse.confirm", EmoteReference.WARNING, housePrice, finalContent);
            InteractiveOperations.create(ctx.getChannel(), ctx.getAuthor().getIdLong(), 30, (e) -> {
                if (!e.getAuthor().equals(ctx.getAuthor()))
                    return Operation.IGNORED;
                if (e.getMessage().getContentRaw().equalsIgnoreCase("yes")) {
                    var playerConfirmed = ctx.getPlayer();
                    var playerInventoryConfirmed = playerConfirmed.getInventory();
                    var dbUserConfirmed = ctx.getDBUser();
                    var marriageConfirmed = dbUserConfirmed.getData().getMarriage();
                    // People like to mess around lol.
                    if (!playerInventoryConfirmed.containsItem(ItemReference.HOUSE)) {
                        ctx.sendLocalized("commands.marry.buyhouse.no_house");
                        return Operation.COMPLETED;
                    }
                    if (playerConfirmed.getCurrentMoney() < housePrice) {
                        ctx.sendLocalized("commands.marry.buyhouse.not_enough_money");
                        return Operation.COMPLETED;
                    }
                    playerInventoryConfirmed.process(new ItemStack(ItemReference.HOUSE, -1));
                    playerConfirmed.removeMoney(housePrice);
                    playerConfirmed.save();
                    marriageConfirmed.getData().setHasHouse(true);
                    marriageConfirmed.getData().setHouseName(finalContent);
                    marriageConfirmed.save();
                    ctx.sendLocalized("commands.marry.buyhouse.success", EmoteReference.POPPER, housePrice, finalContent);
                    return Operation.COMPLETED;
                }
                if (e.getMessage().getContentRaw().equalsIgnoreCase("no")) {
                    ctx.sendLocalized("commands.marry.buyhouse.cancel_success", EmoteReference.CORRECT);
                    return Operation.COMPLETED;
                }
                return Operation.IGNORED;
            });
        }
    }).createSubCommandAlias("house", "buyhouse");
    marryCommand.addSubCommand("car", new SubCommand() {

        @Override
        public String description() {
            return "Buys a car to travel in. You need to buy a ~~cat~~ car in market first. Usage: `~>marry buycar <name>`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var player = ctx.getPlayer();
            var playerInventory = player.getInventory();
            var dbUser = ctx.getDBUser();
            var marriage = dbUser.getData().getMarriage();
            if (marriage == null) {
                ctx.sendLocalized("commands.marry.general.not_married", EmoteReference.ERROR);
                return;
            }
            if (!playerInventory.containsItem(ItemReference.CAR)) {
                ctx.sendLocalized("commands.marry.buycar.no_car", EmoteReference.ERROR);
                return;
            }
            if (player.getCurrentMoney() < carPrice) {
                ctx.sendLocalized("commands.marry.buycar.not_enough_money", EmoteReference.ERROR, carPrice);
                return;
            }
            if (content.isEmpty()) {
                ctx.sendLocalized("commands.marry.buycar.no_name", EmoteReference.ERROR);
                return;
            }
            content = content.replace("\n", "").trim();
            if (content.length() > 150) {
                ctx.sendLocalized("commands.pet.buy.too_long", EmoteReference.ERROR);
                return;
            }
            var finalContent = Utils.HTTP_URL.matcher(content).replaceAll("-url-");
            ctx.sendLocalized("commands.marry.buycar.confirm", EmoteReference.WARNING, carPrice, content);
            InteractiveOperations.create(ctx.getChannel(), ctx.getAuthor().getIdLong(), 30, (e) -> {
                if (!e.getAuthor().equals(ctx.getAuthor()))
                    return Operation.IGNORED;
                if (e.getMessage().getContentRaw().equalsIgnoreCase("yes")) {
                    var playerConfirmed = ctx.getPlayer();
                    var playerInventoryConfirmed = playerConfirmed.getInventory();
                    var dbUserConfirmed = ctx.getDBUser();
                    var marriageConfirmed = dbUserConfirmed.getData().getMarriage();
                    // People like to mess around lol.
                    if (!playerInventoryConfirmed.containsItem(ItemReference.CAR)) {
                        ctx.sendLocalized("commands.marry.buycar.no_car");
                        return Operation.COMPLETED;
                    }
                    if (playerConfirmed.getCurrentMoney() < carPrice) {
                        ctx.sendLocalized("commands.marry.buycar.not_enough_money");
                        return Operation.COMPLETED;
                    }
                    playerInventoryConfirmed.process(new ItemStack(ItemReference.CAR, -1));
                    playerConfirmed.removeMoney(carPrice);
                    playerConfirmed.save();
                    marriageConfirmed.getData().setHasCar(true);
                    marriageConfirmed.getData().setCarName(finalContent);
                    marriageConfirmed.save();
                    ctx.sendLocalized("commands.marry.buycar.success", EmoteReference.POPPER, carPrice, finalContent);
                    return Operation.COMPLETED;
                }
                if (e.getMessage().getContentRaw().equalsIgnoreCase("no")) {
                    ctx.sendLocalized("commands.marry.buycar.cancel_success", EmoteReference.CORRECT);
                    return Operation.COMPLETED;
                }
                return Operation.IGNORED;
            });
        }
    }).createSubCommandAlias("car", "buycar");
    IncreasingRateLimiter tzRatelimit = new IncreasingRateLimiter.Builder().limit(1).spamTolerance(2).cooldown(2, TimeUnit.DAYS).maxCooldown(2, TimeUnit.DAYS).randomIncrement(false).premiumAware(false).pool(MantaroData.getDefaultJedisPool()).prefix("marriage-tz").build();
    marryCommand.addSubCommand("timezone", new SubCommand() {

        @Override
        public String description() {
            return "Sets the timezone for your marriage. Useful for pet sleep times.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var dbUser = ctx.getDBUser();
            var marriage = dbUser.getData().getMarriage();
            if (content.isEmpty()) {
                ctx.sendLocalized("commands.marry.timezone.no_content", EmoteReference.ERROR);
                return;
            }
            if (marriage == null) {
                ctx.sendLocalized("commands.marry.general.not_married", EmoteReference.ERROR);
                return;
            }
            String timezone = content;
            if (// Avoid replacing valid zone IDs / uppercasing them.
            offsetRegex.matcher(timezone).matches())
                timezone = content.toUpperCase().replace("UTC", "GMT");
            if (!Utils.isValidTimeZone(timezone)) {
                ctx.sendLocalized("commands.marry.timezone.invalid", EmoteReference.ERROR);
                return;
            }
            if (!RatelimitUtils.ratelimit(tzRatelimit, ctx)) {
                return;
            }
            marriage.getData().setTimezone(timezone);
            marriage.save();
            dbUser.save();
            ctx.sendLocalized("commands.marry.timezone.success", EmoteReference.CORRECT, timezone);
        }
    });
    marryCommand.addSubCommand("status", new SubCommand() {

        @Override
        public String description() {
            return "Check your marriage status.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            if (!ctx.getSelfMember().hasPermission(ctx.getChannel(), Permission.MESSAGE_EMBED_LINKS)) {
                ctx.sendLocalized("general.missing_embed_permissions");
                return;
            }
            final var author = ctx.getAuthor();
            final var dbUser = ctx.getDBUser();
            final var dbUserData = dbUser.getData();
            final var currentMarriage = dbUserData.getMarriage();
            // What status would we have without marriage? Well, we can be unmarried omegalul.
            if (currentMarriage == null) {
                ctx.sendLocalized("commands.marry.status.no_marriage", EmoteReference.SAD);
                return;
            }
            final var data = currentMarriage.getData();
            // Can we find the user this is married to?
            final var marriedTo = ctx.retrieveUserById(currentMarriage.getOtherPlayer(author.getId()));
            if (marriedTo == null) {
                ctx.sendLocalized("commands.marry.loveletter.cannot_see", EmoteReference.ERROR);
                return;
            }
            // Get the current love letter.
            var loveLetter = data.getLoveLetter();
            if (loveLetter == null || loveLetter.isEmpty()) {
                loveLetter = languageContext.get("general.none");
            }
            final var marriedDBUser = ctx.getDBUser(marriedTo);
            final var dateFormat = Utils.formatDate(data.getMarriageCreationMillis(), dbUserData.getLang());
            final var eitherHasWaifus = !(dbUserData.getWaifus().isEmpty() && marriedDBUser.getData().getWaifus().isEmpty());
            final var marriedToName = dbUserData.isPrivateTag() ? marriedTo.getName() : marriedTo.getAsTag();
            final var authorName = dbUserData.isPrivateTag() ? author.getName() : author.getAsTag();
            final var daysMarried = TimeUnit.of(ChronoUnit.MILLIS).toDays(System.currentTimeMillis() - data.getMarriageCreationMillis());
            EmbedBuilder embedBuilder = new EmbedBuilder().setThumbnail(author.getEffectiveAvatarUrl()).setAuthor(languageContext.get("commands.marry.status.header"), null, author.getEffectiveAvatarUrl()).setColor(ctx.getMemberColor()).setDescription(languageContext.get("commands.marry.status.description_format").formatted(EmoteReference.HEART, authorName, marriedToName)).addField(EmoteReference.CALENDAR2.toHeaderString() + languageContext.get("commands.marry.status.date"), dateFormat, false).addField(EmoteReference.CLOCK.toHeaderString() + languageContext.get("commands.marry.status.age"), daysMarried + " " + languageContext.get("general.days"), false).addField(EmoteReference.LOVE_LETTER.toHeaderString() + languageContext.get("commands.marry.status.love_letter"), loveLetter, false).addField(EmoteReference.ZAP.toHeaderString() + languageContext.get("commands.marry.status.waifus"), String.valueOf(eitherHasWaifus), false).setFooter("Marriage ID: " + currentMarriage.getId(), author.getEffectiveAvatarUrl());
            if (data.hasHouse()) {
                var houseName = data.getHouseName().replace("\n", "").trim();
                embedBuilder.addField(EmoteReference.HOUSE.toHeaderString() + languageContext.get("commands.marry.status.house"), houseName, true);
            }
            if (data.hasCar()) {
                var carName = data.getCarName().replace("\n", "").trim();
                embedBuilder.addField(EmoteReference.CAR.toHeaderString() + languageContext.get("commands.marry.status.car"), carName, true);
            }
            if (data.getPet() != null) {
                var pet = data.getPet();
                var petType = data.getPet().getType();
                embedBuilder.addField(EmoteReference.PET_HOUSE.toHeaderString() + languageContext.get("commands.marry.status.pet"), pet.getName() + " (" + petType.getName() + ")", false);
            }
            ctx.send(embedBuilder.build());
        }
    }).createSubCommandAlias("status", "stats");
    cr.registerAlias("marry", "marriage");
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Badge(net.kodehawa.mantarobot.commands.currency.profile.Badge) Color(java.awt.Color) Module(net.kodehawa.mantarobot.core.modules.Module) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) Permission(net.dv8tion.jda.api.Permission) Utils(net.kodehawa.mantarobot.utils.Utils) User(net.dv8tion.jda.api.entities.User) ITreeCommand(net.kodehawa.mantarobot.core.modules.commands.base.ITreeCommand) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) DBUser(net.kodehawa.mantarobot.db.entities.DBUser) Inventory(net.kodehawa.mantarobot.db.entities.helpers.Inventory) Subscribe(com.google.common.eventbus.Subscribe) SimpleCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleCommand) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) ItemStack(net.kodehawa.mantarobot.commands.currency.item.ItemStack) Player(net.kodehawa.mantarobot.db.entities.Player) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) UserData(net.kodehawa.mantarobot.db.entities.helpers.UserData) ItemReference(net.kodehawa.mantarobot.commands.currency.item.ItemReference) InteractiveOperations(net.kodehawa.mantarobot.core.listeners.operations.InteractiveOperations) Marriage(net.kodehawa.mantarobot.db.entities.Marriage) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) UUID(java.util.UUID) Instant(java.time.Instant) DBGuild(net.kodehawa.mantarobot.db.entities.DBGuild) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) TimeUnit(java.util.concurrent.TimeUnit) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) ChronoUnit(java.time.temporal.ChronoUnit) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) Pattern(java.util.regex.Pattern) Operation(net.kodehawa.mantarobot.core.listeners.operations.core.Operation) Player(net.kodehawa.mantarobot.db.entities.Player) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) User(net.dv8tion.jda.api.entities.User) DBUser(net.kodehawa.mantarobot.db.entities.DBUser) UserData(net.kodehawa.mantarobot.db.entities.helpers.UserData) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) DBGuild(net.kodehawa.mantarobot.db.entities.DBGuild) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) ITreeCommand(net.kodehawa.mantarobot.core.modules.commands.base.ITreeCommand) SimpleCommand(net.kodehawa.mantarobot.core.modules.commands.SimpleCommand) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) ITreeCommand(net.kodehawa.mantarobot.core.modules.commands.base.ITreeCommand) DBUser(net.kodehawa.mantarobot.db.entities.DBUser) ItemStack(net.kodehawa.mantarobot.commands.currency.item.ItemStack) UUID(java.util.UUID) Marriage(net.kodehawa.mantarobot.db.entities.Marriage) ITreeCommand(net.kodehawa.mantarobot.core.modules.commands.base.ITreeCommand) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) Inventory(net.kodehawa.mantarobot.db.entities.helpers.Inventory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Subscribe(com.google.common.eventbus.Subscribe)

Aggregations

Subscribe (com.google.common.eventbus.Subscribe)7 Context (net.kodehawa.mantarobot.core.modules.commands.base.Context)7 HelpContent (net.kodehawa.mantarobot.core.modules.commands.help.HelpContent)7 IncreasingRateLimiter (net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter)7 List (java.util.List)5 TimeUnit (java.util.concurrent.TimeUnit)5 CommandRegistry (net.kodehawa.mantarobot.core.CommandRegistry)5 Module (net.kodehawa.mantarobot.core.modules.Module)5 SimpleCommand (net.kodehawa.mantarobot.core.modules.commands.SimpleCommand)5 CommandCategory (net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory)5 I18nContext (net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext)5 MantaroData (net.kodehawa.mantarobot.data.MantaroData)5 Utils (net.kodehawa.mantarobot.utils.Utils)5 EmoteReference (net.kodehawa.mantarobot.utils.commands.EmoteReference)5 RatelimitUtils (net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils)5 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)4 User (net.dv8tion.jda.api.entities.User)4 Badge (net.kodehawa.mantarobot.commands.currency.profile.Badge)4 SubCommand (net.kodehawa.mantarobot.core.modules.commands.SubCommand)4 Command (net.kodehawa.mantarobot.core.modules.commands.base.Command)4