Search in sources :

Example 6 with I18nContext

use of net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext in project MantaroBot by Mantaro.

the class MessageCmds method prune.

@Subscribe
public void prune(CommandRegistry cr) {
    var pruneCmd = cr.register("prune", new TreeCommand(CommandCategory.MODERATION) {

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

                @Override
                protected void call(Context ctx, I18nContext languageContext, String content) {
                    var args = ctx.getArguments();
                    if (content.isEmpty()) {
                        ctx.sendLocalized("commands.prune.no_messages_specified", EmoteReference.ERROR);
                        return;
                    }
                    var mentionedUsers = ctx.getMentionedUsers();
                    var amount = 5;
                    if (args.length > 0) {
                        try {
                            amount = Integer.parseInt(args[0]);
                            if (amount < 3) {
                                amount = 3;
                            }
                        } catch (Exception e) {
                            ctx.sendLocalized("commands.prune.not_valid", EmoteReference.ERROR);
                            return;
                        }
                    }
                    if (!mentionedUsers.isEmpty()) {
                        List<Long> users = mentionedUsers.stream().map(User::getIdLong).collect(Collectors.toList());
                        final var finalAmount = amount;
                        ctx.getChannel().getHistory().retrievePast(100).queue(messageHistory -> getMessageHistory(ctx, messageHistory, finalAmount, "commands.prune.mention_no_messages", message -> users.contains(message.getAuthor().getIdLong())), error -> ctx.sendLocalized("commands.prune.error_retrieving", EmoteReference.ERROR, error.getClass().getSimpleName(), error.getMessage()));
                        return;
                    }
                    ctx.getChannel().getHistory().retrievePast(Math.min(amount, 100)).queue(messageHistory -> prune(ctx, messageHistory), error -> {
                        ctx.sendLocalized("commands.prune.error_retrieving", EmoteReference.ERROR, error.getClass().getSimpleName(), error.getMessage());
                        error.printStackTrace();
                    });
                }
            };
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Prunes X amount of messages from a channel. Requires Message Manage permission.").setUsage("`~>prune <messages> [@user...]`").addParameter("messages", "Number of messages from 4 to 100.").addParameterOptional("@user...", "Prunes messages only from mentioned users.").build();
        }
    });
    pruneCmd.setPredicate(ctx -> {
        if (!ctx.getMember().hasPermission(Permission.MESSAGE_MANAGE)) {
            ctx.sendLocalized("commands.prune.no_permissions_user", EmoteReference.ERROR);
            return false;
        }
        if (!ctx.getSelfMember().hasPermission(Permission.MESSAGE_MANAGE)) {
            ctx.sendLocalized("commands.prune.no_permissions", EmoteReference.ERROR);
            return false;
        }
        return true;
    });
    pruneCmd.addSubCommand("bot", new SubCommand() {

        @Override
        public String description() {
            return "Prune bot messages. It takes the number of messages as an argument.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var args = ctx.getArguments();
            var amount = 100;
            if (args.length >= 1) {
                try {
                    amount = Integer.parseInt(args[0]);
                    if (amount < 3) {
                        amount = 3;
                    }
                } catch (Exception e) {
                    ctx.sendLocalized("commands.prune.not_valid", EmoteReference.ERROR);
                    return;
                }
            }
            final var finalAmount = amount;
            ctx.getChannel().getHistory().retrievePast(100).queue(messageHistory -> {
                String prefix = MantaroData.db().getGuild(ctx.getGuild()).getData().getGuildCustomPrefix();
                getMessageHistory(ctx, messageHistory, finalAmount, "commands.prune.bots_no_messages", message -> message.getAuthor().isBot() || message.getContentRaw().startsWith(prefix == null ? "~>" : prefix));
            }, error -> {
                ctx.sendLocalized("commands.prune.error_retrieving", EmoteReference.ERROR, error.getClass().getSimpleName(), error.getMessage());
                error.printStackTrace();
            });
        }
    });
    pruneCmd.addSubCommand("nopins", new SubCommand() {

        @Override
        public String description() {
            return "Prune messages that aren't pinned. It takes the number of messages as an argument.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var args = ctx.getArguments();
            var amount = 100;
            if (args.length >= 1) {
                try {
                    amount = Integer.parseInt(args[0]);
                    if (amount < 3) {
                        amount = 3;
                    }
                } catch (Exception e) {
                    ctx.sendLocalized("commands.prune.not_valid", EmoteReference.ERROR);
                    return;
                }
            }
            final var finalAmount = amount;
            ctx.getChannel().getHistory().retrievePast(100).queue(messageHistory -> getMessageHistory(ctx, messageHistory, finalAmount, "commands.prune.no_pins_no_messages", message -> !message.isPinned()), error -> {
                ctx.sendLocalized("commands.prune.error_retrieving", EmoteReference.ERROR, error.getClass().getSimpleName(), error.getMessage());
                error.printStackTrace();
            });
        }
    });
}
Also used : I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) Message(net.dv8tion.jda.api.entities.Message) Module(net.kodehawa.mantarobot.core.modules.Module) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) PermissionException(net.dv8tion.jda.api.exceptions.PermissionException) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) Predicate(java.util.function.Predicate) Permission(net.dv8tion.jda.api.Permission) Collectors(java.util.stream.Collectors) User(net.dv8tion.jda.api.entities.User) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) ModLog(net.kodehawa.mantarobot.commands.moderation.ModLog) List(java.util.List) OffsetDateTime(java.time.OffsetDateTime) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) Subscribe(com.google.common.eventbus.Subscribe) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) User(net.dv8tion.jda.api.entities.User) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) PermissionException(net.dv8tion.jda.api.exceptions.PermissionException) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) Command(net.kodehawa.mantarobot.core.modules.commands.base.Command) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) 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 7 with I18nContext

use of net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext 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)

Example 8 with I18nContext

use of net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext in project MantaroBot by Mantaro.

the class DebugCmds method ping.

@Subscribe
public void ping(CommandRegistry cr) {
    final IncreasingRateLimiter rateLimiter = new IncreasingRateLimiter.Builder().limit(1).spamTolerance(2).cooldown(2, TimeUnit.SECONDS).maxCooldown(30, TimeUnit.SECONDS).randomIncrement(true).pool(MantaroData.getDefaultJedisPool()).prefix("ping").build();
    cr.register("ping", new SimpleCommand(CommandCategory.INFO) {

        @Override
        protected void call(Context ctx, String content, String[] args) {
            I18nContext languageContext = ctx.getLanguageContext();
            if (!RatelimitUtils.ratelimit(rateLimiter, ctx, false))
                return;
            long start = System.currentTimeMillis();
            ctx.getChannel().sendMessage("Pinging...").queue(v -> {
                long ping = System.currentTimeMillis() - start;
                // display: show a random quote, translated.
                v.editMessage(String.format(Utils.getLocaleFromLanguage(ctx.getLanguageContext()), languageContext.get("commands.ping.text"), EmoteReference.MEGA, languageContext.get("commands.ping.display"), ping, ctx.getJDA().getGatewayPing())).queue();
            });
        }

        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Plays Ping-Pong with Discord and prints out the result.").build();
        }
    });
}
Also used : Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) MantaroInfo(net.kodehawa.mantarobot.MantaroInfo) Module(net.kodehawa.mantarobot.core.modules.Module) JDA(net.dv8tion.jda.api.JDA) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) Utils(net.kodehawa.mantarobot.utils.Utils) CommandProcessor(net.kodehawa.mantarobot.core.command.processor.CommandProcessor) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject) LavalinkSocket(lavalink.client.io.LavalinkSocket) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) Map(java.util.Map) 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) CommandListener(net.kodehawa.mantarobot.core.listeners.command.CommandListener) DiscordUtils(net.kodehawa.mantarobot.utils.commands.DiscordUtils) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) IOException(java.io.IOException) AsyncInfoMonitor(net.kodehawa.mantarobot.commands.info.AsyncInfoMonitor) TimeUnit(java.util.concurrent.TimeUnit) APIUtils(net.kodehawa.mantarobot.utils.APIUtils) List(java.util.List) RatelimitUtils(net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils) PlayerLibrary(com.sedmelluq.discord.lavaplayer.tools.PlayerLibrary) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Jedis(redis.clients.jedis.Jedis) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) JDAInfo(net.dv8tion.jda.api.JDAInfo) PreLoadEvent(net.kodehawa.mantarobot.core.listeners.events.PreLoadEvent) Comparator(java.util.Comparator) 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) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) Subscribe(com.google.common.eventbus.Subscribe)

Example 9 with I18nContext

use of net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext in project MantaroBot by Mantaro.

the class RatelimitUtils method ratelimit.

private static boolean ratelimit(IncreasingRateLimiter rateLimiter, String u, GuildMessageReceivedEvent event, I18nContext i18nContext, String extraMessage, boolean spamAware) {
    if (i18nContext == null) {
        // en_US
        i18nContext = new I18nContext();
    }
    if (!config.isHandleRatelimits()) {
        return true;
    }
    RateLimit rateLimit = rateLimiter.limit(u);
    if (rateLimit.getTriesLeft() < 1) {
        event.getChannel().sendMessage(String.format(i18nContext.get("general.ratelimit.header"), EmoteReference.STOPWATCH, i18nContext.get("general.ratelimit_quotes"), Utils.formatDuration(i18nContext, rateLimit.getCooldown())) + (extraMessage == null ? "" : "\n " + extraMessage) + ((rateLimit.getSpamAttempts() > 2 && spamAware) ? "\n\n" + EmoteReference.STOP + i18nContext.get("general.ratelimit.spam_1") : "") + ((rateLimit.getSpamAttempts() > 4 && spamAware) ? i18nContext.get("general.ratelimit.spam_2") : "") + ((rateLimit.getSpamAttempts() > 10 && spamAware) ? i18nContext.get("general.ratelimit.spam_3") : "") + ((rateLimit.getSpamAttempts() > 15 && spamAware) ? i18nContext.get("general.ratelimit.spam_4") : "")).queue();
        // Assuming it's an user RL if it can parse a long since we use UUIDs for other RLs.
        try {
            // noinspection ResultOfMethodCallIgnored
            Long.parseUnsignedLong(u);
            User user;
            try {
                var member = event.getGuild().retrieveMemberById(u, false).complete();
                user = member.getUser();
            } catch (Exception e) {
                log.error("Got a exception while trying to fetch a user that was just spamming?", e);
                return false;
            }
            var guildId = event.getGuild().getId();
            var channelId = event.getChannel().getId();
            var messageId = event.getMessage().getId();
            // If they go over 60 in one attempt, flag.
            if (rateLimit.getSpamAttempts() > 60 && spamAware && !loggedAttemptUsers.contains(user.getId())) {
                loggedAttemptUsers.add(user.getId());
                LogUtils.spambot(user, guildId, channelId, messageId, LogUtils.SpamType.OVER_SPAM_LIMIT);
            }
            onRateLimit(user, guildId, channelId, messageId);
        } catch (Exception e) {
            return false;
        }
        return false;
    }
    return true;
}
Also used : User(net.dv8tion.jda.api.entities.User) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext)

Example 10 with I18nContext

use of net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext in project MantaroBot by Mantaro.

the class ProfileCmd method profile.

@Subscribe
public void profile(CommandRegistry cr) {
    final var rateLimiter = new IncreasingRateLimiter.Builder().limit(// twice every 10m
    2).spamTolerance(2).cooldown(10, TimeUnit.MINUTES).cooldownPenaltyIncrease(10, TimeUnit.SECONDS).maxCooldown(15, TimeUnit.MINUTES).pool(MantaroData.getDefaultJedisPool()).prefix("profile").build();
    final var config = MantaroData.config().get();
    List<ProfileComponent> defaultOrder;
    if (config.isPremiumBot() || config.isSelfHost()) {
        defaultOrder = createLinkedList(HEADER, CREDITS, LEVEL, REPUTATION, BIRTHDAY, MARRIAGE, INVENTORY, BADGES, PET);
    } else {
        defaultOrder = createLinkedList(HEADER, CREDITS, OLD_CREDITS, LEVEL, REPUTATION, BIRTHDAY, MARRIAGE, INVENTORY, BADGES, PET);
    }
    List<ProfileComponent> noOldOrder = createLinkedList(HEADER, CREDITS, LEVEL, REPUTATION, BIRTHDAY, MARRIAGE, INVENTORY, BADGES, PET);
    TreeCommand profileCommand = cr.register("profile", 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) {
                    var optionalArguments = ctx.getOptionalArguments();
                    content = Utils.replaceArguments(optionalArguments, content, "season", "s").trim();
                    var isSeasonal = ctx.isSeasonal();
                    var finalContent = content;
                    ctx.findMember(content, members -> {
                        SeasonPlayer seasonalPlayer = null;
                        var userLooked = ctx.getAuthor();
                        var memberLooked = ctx.getMember();
                        if (!finalContent.isEmpty()) {
                            var found = CustomFinderUtil.findMember(finalContent, members, ctx);
                            if (found == null) {
                                return;
                            }
                            userLooked = found.getUser();
                            memberLooked = found;
                        }
                        if (userLooked.isBot()) {
                            ctx.sendLocalized("commands.profile.bot_notice", EmoteReference.ERROR);
                            return;
                        }
                        var player = ctx.getPlayer(userLooked);
                        var dbUser = ctx.getDBUser(userLooked);
                        var playerData = player.getData();
                        var userData = dbUser.getData();
                        var inv = player.getInventory();
                        // Cache waifu value.
                        playerData.setWaifuCachedValue(WaifuCmd.calculateWaifuValue(player, userLooked).getFinalValue());
                        // start of badge assigning
                        var mh = MantaroBot.getInstance().getShardManager().getGuildById("213468583252983809");
                        var mhMember = mh == null ? null : ctx.retrieveMemberById(memberLooked.getUser().getId(), false);
                        Badge.assignBadges(player, player.getStats(), dbUser);
                        var christmasBadgeAssign = inv.asList().stream().map(ItemStack::getItem).anyMatch(it -> it.equals(ItemReference.CHRISTMAS_TREE_SPECIAL) || it.equals(ItemReference.BELL_SPECIAL));
                        // Manual badges
                        if (config.isOwner(userLooked)) {
                            playerData.addBadgeIfAbsent(Badge.DEVELOPER);
                        }
                        if (christmasBadgeAssign) {
                            playerData.addBadgeIfAbsent(Badge.CHRISTMAS);
                        }
                        // Requires a valid Member in Mantaro Hub.
                        if (mhMember != null) {
                            // Admin
                            if (containsRole(mhMember, 315910951994130432L, 642089477828902912L)) {
                                playerData.addBadgeIfAbsent(Badge.COMMUNITY_ADMIN);
                            }
                            // Patron - Donator
                            if (containsRole(mhMember, 290902183300431872L, 290257037072531466L)) {
                                playerData.addBadgeIfAbsent(Badge.DONATOR_2);
                            }
                            // Translator
                            if (containsRole(mhMember, 407156441812828162L)) {
                                playerData.addBadgeIfAbsent(Badge.TRANSLATOR);
                            }
                        }
                        // end of badge assigning
                        var badges = playerData.getBadges();
                        Collections.sort(badges);
                        if (isSeasonal) {
                            seasonalPlayer = ctx.getSeasonPlayer(userLooked);
                        }
                        var marriage = ctx.getMarriage(userData);
                        var ringHolder = player.getInventory().containsItem(ItemReference.RING) && marriage != null;
                        var holder = new ProfileComponent.Holder(userLooked, player, seasonalPlayer, dbUser, marriage, badges);
                        var profileBuilder = new EmbedBuilder();
                        var description = languageContext.get("commands.profile.no_desc");
                        if (playerData.getDescription() != null) {
                            description = player.getData().getDescription();
                        }
                        profileBuilder.setAuthor((ringHolder ? EmoteReference.RING : "") + String.format(languageContext.get("commands.profile.header"), memberLooked.getEffectiveName()), null, userLooked.getEffectiveAvatarUrl()).setDescription(description).setThumbnail(userLooked.getEffectiveAvatarUrl()).setColor(ctx.getMemberColor(memberLooked)).setFooter(ProfileComponent.FOOTER.getContent().apply(holder, languageContext), ctx.getAuthor().getEffectiveAvatarUrl());
                        var hasCustomOrder = dbUser.isPremium() && !playerData.getProfileComponents().isEmpty();
                        var usedOrder = hasCustomOrder ? playerData.getProfileComponents() : defaultOrder;
                        if ((!config.isPremiumBot() && player.getOldMoney() < 5000 && !hasCustomOrder) || (playerData.isHiddenLegacy() && !hasCustomOrder)) {
                            usedOrder = noOldOrder;
                        }
                        for (var component : usedOrder) {
                            profileBuilder.addField(component.getTitle(languageContext), component.getContent().apply(holder, languageContext), component.isInline());
                        }
                        ctx.send(profileBuilder.build());
                        // We don't need to update stats if someone else views your profile
                        if (player.getUserId().equals(ctx.getAuthor().getId())) {
                            player.saveUpdating();
                        }
                    });
                }
            };
        }

        // If you wonder why is this so short compared to before, subcommand descriptions will do the trick on telling me what they do.
        @Override
        public HelpContent help() {
            return new HelpContent.Builder().setDescription("Retrieves your current user profile.").setUsage("To retrieve your profile use `~>profile`. You can also use `~>profile @mention`\n" + "*The profile command only shows the 5 most important badges.* Use `~>badges` to get a complete list!").addParameter("@mention", "A user mention (ping)").setSeasonal(true).build();
        }
    });
    profileCommand.setPredicate(ctx -> {
        if (!ctx.getSelfMember().hasPermission(ctx.getChannel(), Permission.MESSAGE_EMBED_LINKS)) {
            ctx.sendLocalized("general.missing_embed_permissions");
            return false;
        }
        return true;
    });
    profileCommand.addSubCommand("toggleaction", new SubCommand() {

        @Override
        public String description() {
            return "Toggles the ability to do action commands to you.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var dbUser = ctx.getDBUser();
            final var userData = dbUser.getData();
            final var isDisabled = userData.isActionsDisabled();
            if (isDisabled) {
                userData.setActionsDisabled(false);
                ctx.sendLocalized("commands.profile.toggleaction.enabled", EmoteReference.CORRECT);
            } else {
                userData.setActionsDisabled(true);
                ctx.sendLocalized("commands.profile.toggleaction.disabled", EmoteReference.CORRECT);
            }
            dbUser.save();
        }
    });
    profileCommand.addSubCommand("claimlock", new SubCommand() {

        @Override
        public String description() {
            return "Locks you from being claimed. Use `remove` to remove it.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var player = ctx.getPlayer();
            final var playerData = player.getData();
            if (content.equals("remove")) {
                playerData.setClaimLocked(false);
                ctx.sendLocalized("commands.profile.claimlock.removed", EmoteReference.CORRECT);
                player.saveUpdating();
                return;
            }
            if (playerData.isClaimLocked()) {
                ctx.sendLocalized("commands.profile.claimlock.already_locked", EmoteReference.CORRECT);
                return;
            }
            var inventory = player.getInventory();
            if (!inventory.containsItem(ItemReference.CLAIM_KEY)) {
                ctx.sendLocalized("commands.profile.claimlock.no_key", EmoteReference.ERROR);
                return;
            }
            playerData.setClaimLocked(true);
            ctx.sendLocalized("commands.profile.claimlock.success", EmoteReference.CORRECT);
            inventory.process(new ItemStack(ItemReference.CLAIM_KEY, -1));
            player.saveUpdating();
        }
    });
    if (!config.isPremiumBot()) {
        profileCommand.addSubCommand("togglelegacy", new SubCommand() {

            @Override
            public String description() {
                return "Toggles legacy credit display.";
            }

            @Override
            protected void call(Context ctx, I18nContext languageContext, String content) {
                final var player = ctx.getPlayer();
                final var data = player.getData();
                var toSet = !data.isHiddenLegacy();
                data.setHiddenLegacy(toSet);
                player.saveUpdating();
                ctx.sendLocalized("commands.profile.hidelegacy", EmoteReference.CORRECT, data.isHiddenLegacy());
            }
        });
    }
    profileCommand.addSubCommand("inventorysort", new SubCommand() {

        @Override
        public String description() {
            return "Sort your inventory. Possible values: `VALUE, VALUE_TOTAL, AMOUNT, TYPE, RANDOM`.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            final var type = Utils.lookupEnumString(content, InventorySortType.class);
            if (type == null) {
                ctx.sendLocalized("commands.profile.inventorysort.not_valid", EmoteReference.ERROR, Arrays.stream(InventorySortType.values()).map(b1 -> b1.toString().toLowerCase()).collect(Collectors.joining(", ")));
                return;
            }
            final var player = ctx.getPlayer();
            final var playerData = player.getData();
            playerData.setInventorySortType(type);
            player.saveUpdating();
            ctx.sendLocalized("commands.profile.inventorysort.success", EmoteReference.CORRECT, type.toString().toLowerCase());
        }
    });
    profileCommand.addSubCommand("autoequip", new SubCommand() {

        @Override
        public String description() {
            return "Toggles auto-equipping a new tool on break. Use `disable` to disable it.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var user = ctx.getDBUser();
            var data = user.getData();
            if (content.equals("disable")) {
                data.setAutoEquip(false);
                ctx.sendLocalized("commands.profile.autoequip.disable", EmoteReference.CORRECT);
                user.saveUpdating();
                return;
            }
            data.setAutoEquip(true);
            ctx.sendLocalized("commands.profile.autoequip.success", EmoteReference.CORRECT);
            user.saveUpdating();
        }
    });
    // Hide tags from profile/waifu list.
    profileCommand.addSubCommand("hidetag", new SubCommand() {

        @Override
        public String description() {
            return "Hide or show the member id/tag from profile/waifu ls.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var user = ctx.getDBUser();
            var data = user.getData();
            data.setPrivateTag(!data.isPrivateTag());
            user.saveUpdating();
            ctx.sendLocalized("commands.profile.hide_tag.success", EmoteReference.POPPER, data.isPrivateTag());
        }
    });
    profileCommand.addSubCommand("timezone", new SubCommand() {

        @Override
        public String description() {
            return "Set your profile timezone.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var dbUser = ctx.getDBUser();
            var args = ctx.getArguments();
            if (args.length < 1) {
                ctx.sendLocalized("commands.profile.timezone.not_specified", EmoteReference.ERROR);
                return;
            }
            var timezone = content;
            if (offsetRegex.matcher(timezone).matches()) {
                timezone = content.toUpperCase().replace("UTC", "GMT");
            }
            // EST, EDT, etc...
            if (timezone.length() == 3) {
                timezone = timezone.toUpperCase();
            }
            if (timezone.equalsIgnoreCase("reset")) {
                dbUser.getData().setTimezone(null);
                dbUser.saveAsync();
                ctx.sendLocalized("commands.profile.timezone.reset_success", EmoteReference.CORRECT);
                return;
            }
            if (!Utils.isValidTimeZone(timezone)) {
                ctx.sendLocalized("commands.profile.timezone.invalid", EmoteReference.ERROR);
                return;
            }
            try {
                Utils.formatDate(LocalDateTime.now(Utils.timezoneToZoneID(timezone)), dbUser.getData().getLang());
            } catch (DateTimeException e) {
                ctx.sendLocalized("commands.profile.timezone.invalid", EmoteReference.ERROR);
                return;
            }
            var player = ctx.getPlayer();
            if (player.getData().addBadgeIfAbsent(Badge.CALENDAR)) {
                player.saveUpdating();
            }
            dbUser.getData().setTimezone(timezone);
            dbUser.saveUpdating();
            ctx.sendLocalized("commands.profile.timezone.success", EmoteReference.CORRECT, timezone);
        }
    });
    profileCommand.addSubCommand("description", new SubCommand() {

        @Override
        public String description() {
            return "Set your profile description. Use `reset` to reset it.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            if (!RatelimitUtils.ratelimit(rateLimiter, ctx)) {
                return;
            }
            var args = ctx.getArguments();
            var player = ctx.getPlayer();
            var dbUser = ctx.getDBUser();
            if (args.length == 0) {
                ctx.sendLocalized("commands.profile.description.no_argument", EmoteReference.ERROR);
                return;
            }
            if (args[0].equals("clear") || args[0].equals("remove") || args[0].equals("reset")) {
                player.getData().setDescription(null);
                ctx.sendLocalized("commands.profile.description.clear_success", EmoteReference.CORRECT);
                player.saveUpdating();
                return;
            }
            var split = SPLIT_PATTERN.split(content, 2);
            var desc = content;
            var old = false;
            if (split[0].equals("set")) {
                desc = content.replaceFirst("set ", "");
                old = true;
            }
            var MAX_LENGTH = 300;
            if (dbUser.isPremium()) {
                MAX_LENGTH = 500;
            }
            if (args.length < (old ? 2 : 1)) {
                ctx.sendLocalized("commands.profile.description.no_content", EmoteReference.ERROR);
                return;
            }
            if (desc.length() > MAX_LENGTH) {
                ctx.sendLocalized("commands.profile.description.too_long", EmoteReference.ERROR);
                return;
            }
            desc = Utils.DISCORD_INVITE.matcher(desc).replaceAll("-discord invite link-");
            desc = Utils.DISCORD_INVITE_2.matcher(desc).replaceAll("-discord invite link-");
            player.getData().setDescription(desc);
            ctx.sendStrippedLocalized("commands.profile.description.success", EmoteReference.POPPER);
            player.getData().addBadgeIfAbsent(Badge.WRITER);
            player.saveUpdating();
        }
    });
    profileCommand.addSubCommand("displaybadge", new SubCommand() {

        @Override
        public String description() {
            return "Set your profile badge. Use `reset` to reset and `none` to show no badge.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var args = ctx.getArguments();
            if (args.length == 0) {
                ctx.sendLocalized("commands.profile.displaybadge.not_specified", EmoteReference.ERROR);
                return;
            }
            var player = ctx.getPlayer();
            var data = player.getData();
            var arg = args[0];
            if (arg.equalsIgnoreCase("none")) {
                data.setShowBadge(false);
                ctx.sendLocalized("commands.profile.displaybadge.reset_success", EmoteReference.CORRECT);
                player.saveUpdating();
                return;
            }
            if (arg.equalsIgnoreCase("reset")) {
                data.setMainBadge(null);
                data.setShowBadge(true);
                ctx.sendLocalized("commands.profile.displaybadge.important_success", EmoteReference.CORRECT);
                player.saveUpdating();
                return;
            }
            var badge = Badge.lookupFromString(content);
            if (badge == null) {
                ctx.sendLocalized("commands.profile.displaybadge.no_such_badge", EmoteReference.ERROR, player.getData().getBadges().stream().map(Badge::getDisplay).collect(Collectors.joining(", ")));
                return;
            }
            if (!data.getBadges().contains(badge)) {
                ctx.sendLocalized("commands.profile.displaybadge.player_missing_badge", EmoteReference.ERROR, player.getData().getBadges().stream().map(Badge::getDisplay).collect(Collectors.joining(", ")));
                return;
            }
            data.setShowBadge(true);
            data.setMainBadge(badge);
            player.saveUpdating();
            ctx.sendLocalized("commands.profile.displaybadge.success", EmoteReference.CORRECT, badge.display);
        }
    });
    profileCommand.addSubCommand("language", new SubCommand() {

        @Override
        public String description() {
            return "Set your profile language. Available langs: `~>lang`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            if (content.isEmpty()) {
                ctx.sendLocalized("commands.profile.lang.nothing_specified", EmoteReference.ERROR);
                return;
            }
            var dbUser = ctx.getDBUser();
            if (content.equalsIgnoreCase("reset")) {
                dbUser.getData().setLang(null);
                dbUser.saveUpdating();
                ctx.sendLocalized("commands.profile.lang.reset_success", EmoteReference.CORRECT);
                return;
            }
            if (I18n.isValidLanguage(content)) {
                dbUser.getData().setLang(content);
                // Create new I18n context based on the new language choice.
                var newContext = new I18nContext(ctx.getDBGuild().getData(), dbUser.getData());
                dbUser.saveUpdating();
                ctx.getChannel().sendMessageFormat(newContext.get("commands.profile.lang.success"), EmoteReference.CORRECT, content).queue();
            } else {
                ctx.sendLocalized("commands.profile.lang.invalid", EmoteReference.ERROR);
            }
        }
    }).createSubCommandAlias("language", "lang");
    profileCommand.addSubCommand("stats", new SubCommand() {

        @Override
        public String description() {
            return "Check profile statistics.";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            ctx.findMember(content, members -> {
                var member = CustomFinderUtil.findMemberDefault(content, members, ctx, ctx.getMember());
                if (member == null) {
                    return;
                }
                var toLookup = member.getUser();
                if (toLookup.isBot()) {
                    ctx.sendLocalized("commands.profile.bot_notice", EmoteReference.ERROR);
                    return;
                }
                var player = ctx.getPlayer(toLookup);
                var dbUser = ctx.getDBUser(toLookup);
                List<MessageEmbed.Field> fields = new LinkedList<>();
                for (StatsComponent component : StatsComponent.values()) {
                    fields.add(new MessageEmbed.Field(component.getEmoji() + component.getName(ctx), component.getContent(new StatsComponent.Holder(ctx, languageContext, player, dbUser, toLookup)), false));
                }
                var splitFields = DiscordUtils.divideFields(9, fields);
                var embed = new EmbedBuilder().setThumbnail(toLookup.getEffectiveAvatarUrl()).setAuthor(languageContext.get("commands.profile.stats.header").formatted(toLookup.getName()), null, toLookup.getEffectiveAvatarUrl()).setDescription(String.format(languageContext.get("general.buy_sell_paged_react"), String.format(languageContext.get("general.reaction_timeout"), 200))).setColor(ctx.getMemberColor()).setFooter("Thanks for using Mantaro! %s".formatted(EmoteReference.HEART), ctx.getGuild().getIconUrl());
                DiscordUtils.listButtons(ctx, 200, embed, splitFields);
            });
        }
    });
    profileCommand.addSubCommand("widgets", new SubCommand() {

        @Override
        public String description() {
            return "Set profile widgets and order. Arguments: `widget`, `ls` or `reset`";
        }

        @Override
        protected void call(Context ctx, I18nContext languageContext, String content) {
            var user = ctx.getDBUser();
            if (!user.isPremium()) {
                ctx.sendLocalized("commands.profile.display.not_premium", EmoteReference.ERROR);
                return;
            }
            var player = ctx.getPlayer();
            var playerData = player.getData();
            if (content.equalsIgnoreCase("ls") || content.equalsIgnoreCase("Is")) {
                ctx.sendFormat(languageContext.get("commands.profile.display.ls") + languageContext.get("commands.profile.display.example"), EmoteReference.ZAP, EmoteReference.BLUE_SMALL_MARKER, defaultOrder.stream().map(Enum::name).collect(Collectors.joining(", ")), playerData.getProfileComponents().size() == 0 ? "Not personalized" : playerData.getProfileComponents().stream().map(Enum::name).collect(Collectors.joining(", ")));
                return;
            }
            if (content.equalsIgnoreCase("reset")) {
                playerData.getProfileComponents().clear();
                player.save();
                ctx.sendLocalized("commands.profile.display.reset", EmoteReference.CORRECT);
                return;
            }
            var splitContent = content.replace(",", "").split("\\s+");
            // new list of profile components
            List<ProfileComponent> newComponents = new LinkedList<>();
            for (var cmt : splitContent) {
                var component = ProfileComponent.lookupFromString(cmt);
                if (component != null && component.isAssignable()) {
                    newComponents.add(component);
                }
            }
            if (newComponents.size() < 3) {
                ctx.sendFormat(languageContext.get("commands.profile.display.not_enough") + languageContext.get("commands.profile.display.example"), EmoteReference.WARNING);
                return;
            }
            playerData.setProfileComponents(newComponents);
            player.save();
            ctx.sendLocalized("commands.profile.display.success", EmoteReference.CORRECT, newComponents.stream().map(Enum::name).collect(Collectors.joining(", ")));
        }
    });
    cr.registerAlias("profile", "me");
}
Also used : Badge(net.kodehawa.mantarobot.commands.currency.profile.Badge) StatsComponent(net.kodehawa.mantarobot.commands.currency.profile.StatsComponent) Module(net.kodehawa.mantarobot.core.modules.Module) Arrays(java.util.Arrays) 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) LocalDateTime(java.time.LocalDateTime) Member(net.dv8tion.jda.api.entities.Member) SeasonPlayer(net.kodehawa.mantarobot.commands.currency.seasons.SeasonPlayer) MantaroBot(net.kodehawa.mantarobot.MantaroBot) CustomFinderUtil(net.kodehawa.mantarobot.utils.commands.CustomFinderUtil) PlayerEquipment(net.kodehawa.mantarobot.commands.currency.item.PlayerEquipment) Role(net.dv8tion.jda.api.entities.Role) CommandRegistry(net.kodehawa.mantarobot.core.CommandRegistry) Utils.createLinkedList(net.kodehawa.mantarobot.utils.Utils.createLinkedList) Subscribe(com.google.common.eventbus.Subscribe) 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) DateTimeException(java.time.DateTimeException) DiscordUtils(net.kodehawa.mantarobot.utils.commands.DiscordUtils) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) I18n(net.kodehawa.mantarobot.data.I18n) ItemReference(net.kodehawa.mantarobot.commands.currency.item.ItemReference) SPLIT_PATTERN(net.kodehawa.mantarobot.utils.StringUtils.SPLIT_PATTERN) IncreasingRateLimiter(net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter) ProfileComponent(net.kodehawa.mantarobot.commands.currency.profile.ProfileComponent) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Collectors(java.util.stream.Collectors) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) java.awt(java.awt) 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) CommandCategory(net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) InventorySortType(net.kodehawa.mantarobot.commands.currency.profile.inventory.InventorySortType) EmoteReference(net.kodehawa.mantarobot.utils.commands.EmoteReference) MantaroData(net.kodehawa.mantarobot.data.MantaroData) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) MessageEmbed(net.dv8tion.jda.api.entities.MessageEmbed) HelpContent(net.kodehawa.mantarobot.core.modules.commands.help.HelpContent) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) ProfileComponent(net.kodehawa.mantarobot.commands.currency.profile.ProfileComponent) StatsComponent(net.kodehawa.mantarobot.commands.currency.profile.StatsComponent) DateTimeException(java.time.DateTimeException) Utils.createLinkedList(net.kodehawa.mantarobot.utils.Utils.createLinkedList) LinkedList(java.util.LinkedList) List(java.util.List) SeasonPlayer(net.kodehawa.mantarobot.commands.currency.seasons.SeasonPlayer) TreeCommand(net.kodehawa.mantarobot.core.modules.commands.TreeCommand) Context(net.kodehawa.mantarobot.core.modules.commands.base.Context) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) SubCommand(net.kodehawa.mantarobot.core.modules.commands.SubCommand) 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) ItemStack(net.kodehawa.mantarobot.commands.currency.item.ItemStack) I18nContext(net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext) InventorySortType(net.kodehawa.mantarobot.commands.currency.profile.inventory.InventorySortType) Subscribe(com.google.common.eventbus.Subscribe)

Aggregations

I18nContext (net.kodehawa.mantarobot.core.modules.commands.i18n.I18nContext)13 EmoteReference (net.kodehawa.mantarobot.utils.commands.EmoteReference)11 Context (net.kodehawa.mantarobot.core.modules.commands.base.Context)10 MantaroData (net.kodehawa.mantarobot.data.MantaroData)9 Subscribe (com.google.common.eventbus.Subscribe)8 TimeUnit (java.util.concurrent.TimeUnit)8 CommandRegistry (net.kodehawa.mantarobot.core.CommandRegistry)8 Module (net.kodehawa.mantarobot.core.modules.Module)8 CommandCategory (net.kodehawa.mantarobot.core.modules.commands.base.CommandCategory)8 HelpContent (net.kodehawa.mantarobot.core.modules.commands.help.HelpContent)8 Utils (net.kodehawa.mantarobot.utils.Utils)8 List (java.util.List)7 Collectors (java.util.stream.Collectors)7 IncreasingRateLimiter (net.kodehawa.mantarobot.utils.commands.ratelimit.IncreasingRateLimiter)7 RatelimitUtils (net.kodehawa.mantarobot.utils.commands.ratelimit.RatelimitUtils)7 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)6 Permission (net.dv8tion.jda.api.Permission)6 Badge (net.kodehawa.mantarobot.commands.currency.profile.Badge)6 SubCommand (net.kodehawa.mantarobot.core.modules.commands.SubCommand)6 Command (net.kodehawa.mantarobot.core.modules.commands.base.Command)6