Search in sources :

Example 6 with ButtonClickEvent

use of net.dv8tion.jda.api.events.interaction.ButtonClickEvent in project Sx4 by sx4-discord-bot.

the class TradeCommand method onCommand.

public void onCommand(Sx4CommandEvent event, @Argument(value = "user", endless = true) Member member) {
    User user = member.getUser();
    if (user.isBot()) {
        event.replyFailure("You can not trade with bots").queue();
        return;
    }
    if (user.getIdLong() == event.getAuthor().getIdLong()) {
        event.replyFailure("You can not trade with yourself").queue();
        return;
    }
    String prompt = "What %s the user? Make sure you put a space between every thing you want to offer, for example: `2 gold, 200, 5 titanium, 1 coal factory` would offer $200, 5 Titanium, 2 Gold and 1 Coal Factory (Respond Below)";
    AtomicLong userMoneyAtomic = new AtomicLong(0), authorMoneyAtomic = new AtomicLong(0);
    Map<Item, Long> userItems = new HashMap<>(), authorItems = new HashMap<>();
    event.reply(String.format(prompt, "are you offering to")).submit().thenCompose(message -> {
        return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setPredicate(e -> !e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setUnique(event.getAuthor().getIdLong(), event.getChannel().getIdLong()).setTimeout(60).start();
    }).thenCompose(e -> {
        Map.Entry<Long, Map<Item, Long>> trade = this.getTrade(event.getBot().getEconomyManager(), e.getMessage().getContentRaw());
        Map<Item, Long> items = trade.getValue();
        long money = trade.getKey();
        if (items.isEmpty() && money == 0) {
            throw new IllegalArgumentException("No valid or tradeable items or money were supplied");
        }
        userItems.putAll(trade.getValue());
        userMoneyAtomic.set(trade.getKey());
        StringJoiner content = new StringJoiner("\n");
        items.forEach((key, value) -> content.add(value + " " + key.getName()));
        EmbedBuilder embed = new EmbedBuilder().setTitle("What you are offering to " + user.getAsTag()).setDescription((money == 0 ? "" : String.format("$%,d", money)) + (items.isEmpty() ? "" : "\n") + content);
        MessageBuilder message = new MessageBuilder().setEmbeds(embed.build()).setContent(String.format(prompt, "would you like from"));
        return event.reply(message.build()).submit();
    }).thenCompose(message -> {
        return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setPredicate(e -> !e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setUnique(event.getAuthor().getIdLong(), event.getChannel().getIdLong()).setTimeout(60).start();
    }).thenCompose(e -> {
        Map.Entry<Long, Map<Item, Long>> trade = this.getTrade(event.getBot().getEconomyManager(), e.getMessage().getContentRaw());
        authorItems.putAll(trade.getValue());
        long authorMoney = trade.getKey();
        if (authorItems.isEmpty() && authorMoney == 0) {
            throw new IllegalArgumentException("No valid or tradeable items or money were supplied");
        }
        authorMoneyAtomic.set(authorMoney);
        long userMoney = userMoneyAtomic.get();
        StringJoiner authorContent = new StringJoiner("\n");
        authorItems.forEach((key, value) -> authorContent.add(value + " " + key.getName()));
        StringJoiner userContent = new StringJoiner("\n");
        userItems.forEach((key, value) -> userContent.add(value + " " + key.getName()));
        EmbedBuilder embed = new EmbedBuilder().setTitle("Final Trade").addField(user.getAsTag() + " Gets", (userMoney == 0 ? "" : String.format("$%,d", userMoney)) + (userItems.isEmpty() ? "" : "\n") + userContent, false).addField(event.getAuthor().getAsTag() + " Gets", (authorMoney == 0 ? "" : String.format("$%,d", authorMoney)) + (authorItems.isEmpty() ? "" : "\n") + authorContent, false);
        MessageBuilder message = new MessageBuilder().setEmbeds(embed.build()).setActionRows(ActionRow.of(List.of(Button.success("yes", "Yes"), Button.danger("no", "No")))).setAllowedMentions(EnumSet.of(Message.MentionType.USER)).setContent(user.getAsMention() + ", do you accept this trade?");
        return event.reply(message.build()).submit();
    }).thenCompose(message -> {
        return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, user)).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, user)).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
    }).whenCompleteAsync((e, exception) -> {
        Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
        if (cause instanceof CancelException) {
            GenericEvent cancelEvent = ((CancelException) cause).getEvent();
            if (cancelEvent != null) {
                ((ButtonClickEvent) cancelEvent).reply("Cancelled " + event.getConfig().getSuccessEmote()).queue();
            }
            return;
        } else if (cause instanceof TimeoutException) {
            event.reply("Timed out :stopwatch:").queue();
            return;
        } else if (cause instanceof IllegalArgumentException) {
            event.replyFailure(cause.getMessage()).queue();
            return;
        }
        if (ExceptionUtility.sendExceptionally(event, exception)) {
            return;
        }
        event.getMongo().withTransaction(session -> {
            Map<String, Long> types = new HashMap<>();
            Map<Item, Long> combined = new HashMap<>();
            long authorMoney = authorMoneyAtomic.get(), userMoney = userMoneyAtomic.get();
            long totalAuthorWorth = authorMoney;
            for (Item item : authorItems.keySet()) {
                if (item instanceof Envelope) {
                    e.reply("You can not trade envelopes " + event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                } else if (item instanceof Tool) {
                    e.reply("You can not trade tools " + event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
                long amount = authorItems.get(item);
                totalAuthorWorth += item.getPrice() * amount;
                types.compute(item.getName(), (key, value) -> value == null ? amount : value + amount);
                combined.compute(item, (key, value) -> value == null ? -amount : value - amount);
            }
            long totalUserWorth = userMoney;
            for (Item item : userItems.keySet()) {
                if (item instanceof Envelope) {
                    e.reply("You can not trade envelopes " + event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                } else if (item instanceof Tool) {
                    e.reply("You can not trade tools " + event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
                long amount = userItems.get(item);
                totalUserWorth += item.getPrice() * amount;
                types.compute(item.getName(), (key, value) -> value == null ? amount : value + amount);
                combined.compute(item, (key, value) -> value == null ? amount : value + amount);
            }
            types.put("Money", authorMoney + userMoney);
            Map.Entry<String, Long> max = types.entrySet().stream().max(Map.Entry.comparingByValue()).get();
            if ((double) max.getValue() / (totalUserWorth + totalAuthorWorth) >= 0.7D) {
                e.reply(max.getKey() + " cannot make up more than 70% of the trades value " + event.getConfig().getFailureEmote()).queue();
                session.abortTransaction();
                return;
            }
            if (totalUserWorth / totalAuthorWorth > 5 || totalAuthorWorth / totalUserWorth > 5) {
                e.reply("You have to trade at least 20% the worth of the other persons trade " + event.getConfig().getFailureEmote()).queue();
                session.abortTransaction();
                return;
            }
            if (userMoney - authorMoney != 0) {
                List<Bson> authorUpdate = List.of(Operators.set("economy.balance", Operators.let(new Document("balance", Operators.ifNull("$economy.balance", 0L)), Operators.let(new Document("newBalance", Operators.add("$$balance", authorMoney - userMoney)), Operators.cond(Operators.lt("$$newBalance", 0L), "$$balance", "$$newBalance")))));
                UpdateResult authorResult = event.getMongo().getUsers().updateOne(session, Filters.eq("_id", event.getAuthor().getIdLong()), authorUpdate);
                if (authorResult.getModifiedCount() == 0) {
                    e.replyFormat("%s does not have **$%,d** %s", event.getAuthor().getAsTag(), userMoney - authorMoney, event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
                List<Bson> userUpdate = List.of(Operators.set("economy.balance", Operators.let(new Document("balance", Operators.ifNull("$economy.balance", 0L)), Operators.let(new Document("newBalance", Operators.add("$$balance", userMoney - authorMoney)), Operators.cond(Operators.lt("$$newBalance", 0L), "$$balance", "$$newBalance")))));
                UpdateResult userResult = event.getMongo().getUsers().updateOne(session, Filters.eq("_id", user.getIdLong()), userUpdate);
                if (userResult.getModifiedCount() == 0) {
                    e.replyFormat("%s does not have **$%,d** %s", event.getAuthor().getAsTag(), authorMoney - userMoney, event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
            }
            for (Item item : combined.keySet()) {
                long signedAmount = combined.get(item);
                if (signedAmount == 0) {
                    continue;
                }
                boolean author = signedAmount < 0;
                long amount = Math.abs(signedAmount);
                List<Bson> addUpdate = List.of(Operators.set("item", item.toData()), Operators.set("amount", Operators.add(Operators.ifNull("$amount", 0L), amount)));
                event.getMongo().getItems().updateOne(session, Filters.and(Filters.eq("userId", author ? event.getAuthor().getIdLong() : user.getIdLong()), Filters.eq("item.id", item.getId())), addUpdate, new UpdateOptions().upsert(true));
                List<Bson> removeUpdate = List.of(Operators.set("amount", Operators.let(new Document("amount", Operators.ifNull("$amount", 0L)), Operators.cond(Operators.lt(Operators.subtract("$$amount", Operators.sum(Operators.map(Operators.filter(Operators.ifNull("$resets", Collections.EMPTY_LIST), Operators.gt("$$this.time", Operators.nowEpochSecond())), "$$this.amount"))), amount), "$$amount", Operators.subtract("$$amount", amount)))));
                FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().projection(Projections.include("amount", "resets")).returnDocument(ReturnDocument.BEFORE);
                Document data = event.getMongo().getItems().findOneAndUpdate(session, Filters.and(Filters.eq("userId", author ? user.getIdLong() : event.getAuthor().getIdLong()), Filters.eq("item.id", item.getId())), removeUpdate, options);
                long userAmount = data == null ? 0L : data.get("amount", 0L);
                if (userAmount < amount) {
                    e.reply((author ? user.getAsTag() : event.getAuthor().getAsTag()) + " does not have `" + amount + " " + item.getName() + "` " + event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
                CooldownItemStack<Item> cooldownStack = new CooldownItemStack<>(item, data);
                long cooldownAmount = cooldownStack.getCooldownAmount();
                if (userAmount - cooldownAmount < amount) {
                    e.replyFormat("%s has `%,d %s` but **%,d** %s on cooldown %s", author ? user.getAsTag() : event.getAuthor().getAsTag(), userAmount, item.getName(), cooldownAmount, cooldownAmount == 1 ? "is" : "are", event.getConfig().getFailureEmote()).queue();
                    session.abortTransaction();
                    return;
                }
            }
        }).whenComplete((updated, databaseException) -> {
            if (ExceptionUtility.sendExceptionally(event, databaseException) || !updated) {
                return;
            }
            e.reply("All money and items have been traded " + event.getConfig().getSuccessEmote()).queue();
        });
    });
}
Also used : Document(org.bson.Document) java.util(java.util) CancelException(com.sx4.bot.waiter.exception.CancelException) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Permission(net.dv8tion.jda.api.Permission) Member(net.dv8tion.jda.api.entities.Member) User(net.dv8tion.jda.api.entities.User) Bson(org.bson.conversions.Bson) ButtonUtility(com.sx4.bot.utility.ButtonUtility) UpdateResult(com.mongodb.client.result.UpdateResult) com.sx4.bot.entities.economy.item(com.sx4.bot.entities.economy.item) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Button(net.dv8tion.jda.api.interactions.components.Button) Waiter(com.sx4.bot.waiter.Waiter) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) ActionRow(net.dv8tion.jda.api.interactions.components.ActionRow) com.mongodb.client.model(com.mongodb.client.model) Argument(com.jockie.bot.core.argument.Argument) Message(net.dv8tion.jda.api.entities.Message) Operators(com.sx4.bot.database.mongo.model.Operators) Sx4Command(com.sx4.bot.core.Sx4Command) EconomyManager(com.sx4.bot.managers.EconomyManager) CompletionException(java.util.concurrent.CompletionException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) ModuleCategory(com.sx4.bot.category.ModuleCategory) AtomicLong(java.util.concurrent.atomic.AtomicLong) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) MessageReceivedEvent(net.dv8tion.jda.api.events.message.MessageReceivedEvent) User(net.dv8tion.jda.api.entities.User) Document(org.bson.Document) MessageBuilder(net.dv8tion.jda.api.MessageBuilder) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) UpdateResult(com.mongodb.client.result.UpdateResult) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) AtomicLong(java.util.concurrent.atomic.AtomicLong) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) CompletionException(java.util.concurrent.CompletionException) AtomicLong(java.util.concurrent.atomic.AtomicLong) CancelException(com.sx4.bot.waiter.exception.CancelException) Waiter(com.sx4.bot.waiter.Waiter)

Example 7 with ButtonClickEvent

use of net.dv8tion.jda.api.events.interaction.ButtonClickEvent in project Sx4 by sx4-discord-bot.

the class MarriageCommand method remove.

@Command(value = "remove", description = "Divorce someone you are currently married to")
@CommandId(269)
@Redirects({ "divorce" })
@Examples({ "marriage remove @Shea#6653", "marriage remove Shea", "marriage remove all" })
public void remove(Sx4CommandEvent event, @Argument(value = "user | all", endless = true, nullDefault = true) @AlternativeOptions("all") Alternative<Member> option) {
    User author = event.getAuthor();
    if (option == null) {
        Bson filter = Filters.or(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", author.getIdLong()));
        List<Document> marriages = event.getMongo().getMarriages(filter, Projections.include("proposerId", "partnerId")).into(new ArrayList<>());
        if (marriages.isEmpty()) {
            event.replyFailure("You are not married to anyone").queue();
            return;
        }
        List<Long> userIds = marriages.stream().map(marriage -> {
            long partnerId = marriage.getLong("partnerId");
            return partnerId == author.getIdLong() ? marriage.getLong("proposerId") : partnerId;
        }).collect(Collectors.toList());
        PagedResult<Long> paged = new PagedResult<>(event.getBot(), userIds).setAuthor("Divorce", null, author.getEffectiveAvatarUrl()).setTimeout(60).setDisplayFunction(userId -> {
            User other = event.getShardManager().getUserById(userId);
            return (other == null ? "Anonymous#0000" : other.getAsTag()) + " (" + userId + ")";
        });
        paged.onTimeout(() -> event.reply("Timed out :stopwatch:").queue());
        paged.onSelect(select -> {
            long userId = select.getSelected();
            Bson deleteFilter = Filters.or(Filters.and(Filters.eq("proposerId", userId), Filters.eq("partnerId", author.getIdLong())), Filters.and(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", userId)));
            event.getMongo().deleteMarriage(deleteFilter).whenComplete((result, exception) -> {
                if (ExceptionUtility.sendExceptionally(event, exception)) {
                    return;
                }
                User user = event.getShardManager().getUserById(userId);
                event.replySuccess("You are no longer married to **" + (user == null ? "Anonymous#0000" : user.getAsTag()) + "**").queue();
            });
        });
        paged.execute(event);
    } else if (option.isAlternative()) {
        List<Button> buttons = List.of(Button.success("yes", "Yes"), Button.danger("no", "No"));
        event.reply(author.getName() + ", are you sure you want to divorce everyone you are currently married to?").setActionRow(buttons).submit().thenCompose(message -> {
            return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, event.getAuthor())).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, event.getAuthor())).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
        }).whenComplete((e, exception) -> {
            Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
            if (cause instanceof CancelException) {
                GenericEvent cancelEvent = ((CancelException) cause).getEvent();
                if (cancelEvent != null) {
                    ((ButtonClickEvent) cancelEvent).reply("Cancelled " + event.getConfig().getSuccessEmote()).queue();
                }
                return;
            } else if (cause instanceof TimeoutException) {
                event.reply("Timed out :stopwatch:").queue();
                return;
            } else if (ExceptionUtility.sendExceptionally(event, exception)) {
                return;
            }
            Bson filter = Filters.or(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", author.getIdLong()));
            event.getMongo().deleteManyMarriages(filter).whenComplete((result, databaseException) -> {
                if (ExceptionUtility.sendExceptionally(event, databaseException)) {
                    return;
                }
                if (result.getDeletedCount() == 0) {
                    e.reply("You are not married to anyone " + event.getConfig().getFailureEmote()).queue();
                    return;
                }
                e.reply("You are no longer married to anyone " + event.getConfig().getSuccessEmote()).queue();
            });
        });
    } else {
        Member member = option.getValue();
        Bson filter = Filters.or(Filters.and(Filters.eq("proposerId", member.getIdLong()), Filters.eq("partnerId", author.getIdLong())), Filters.and(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", member.getIdLong())));
        event.getMongo().deleteMarriage(filter).whenComplete((result, exception) -> {
            if (ExceptionUtility.sendExceptionally(event, exception)) {
                return;
            }
            if (result.getDeletedCount() == 0) {
                event.replyFailure("You are not married to that user").queue();
                return;
            }
            event.replySuccess("You are no longer married to **" + member.getUser().getAsTag() + "**").queue();
        });
    }
}
Also used : Document(org.bson.Document) CancelException(com.sx4.bot.waiter.exception.CancelException) Command(com.jockie.bot.core.command.Command) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Projections(com.mongodb.client.model.Projections) Cooldown(com.jockie.bot.core.command.Command.Cooldown) CommandId(com.sx4.bot.annotations.command.CommandId) Member(net.dv8tion.jda.api.entities.Member) PagedResult(com.sx4.bot.paged.PagedResult) User(net.dv8tion.jda.api.entities.User) ArrayList(java.util.ArrayList) Filters(com.mongodb.client.model.Filters) Bson(org.bson.conversions.Bson) Redirects(com.sx4.bot.annotations.command.Redirects) Alternative(com.sx4.bot.entities.argument.Alternative) ButtonUtility(com.sx4.bot.utility.ButtonUtility) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Button(net.dv8tion.jda.api.interactions.components.Button) AlternativeOptions(com.sx4.bot.annotations.argument.AlternativeOptions) Waiter(com.sx4.bot.waiter.Waiter) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) ZoneOffset(java.time.ZoneOffset) EnumSet(java.util.EnumSet) Argument(com.jockie.bot.core.argument.Argument) Message(net.dv8tion.jda.api.entities.Message) Sx4Command(com.sx4.bot.core.Sx4Command) Updates(com.mongodb.client.model.Updates) CooldownMessage(com.sx4.bot.annotations.command.CooldownMessage) CompletionException(java.util.concurrent.CompletionException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) ModuleCategory(com.sx4.bot.category.ModuleCategory) List(java.util.List) Examples(com.sx4.bot.annotations.command.Examples) OffsetDateTime(java.time.OffsetDateTime) Sorts(com.mongodb.client.model.Sorts) DateTimeFormatter(java.time.format.DateTimeFormatter) StringJoiner(java.util.StringJoiner) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) User(net.dv8tion.jda.api.entities.User) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Document(org.bson.Document) Bson(org.bson.conversions.Bson) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) CompletionException(java.util.concurrent.CompletionException) ArrayList(java.util.ArrayList) List(java.util.List) CancelException(com.sx4.bot.waiter.exception.CancelException) Member(net.dv8tion.jda.api.entities.Member) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) Redirects(com.sx4.bot.annotations.command.Redirects) Command(com.jockie.bot.core.command.Command) Sx4Command(com.sx4.bot.core.Sx4Command) CommandId(com.sx4.bot.annotations.command.CommandId) Examples(com.sx4.bot.annotations.command.Examples)

Example 8 with ButtonClickEvent

use of net.dv8tion.jda.api.events.interaction.ButtonClickEvent in project Sx4 by sx4-discord-bot.

the class MarriageCommand method add.

@Command(value = "add", description = "Propose to a user and marry them if they accept")
@CommandId(268)
@Redirects({ "marry" })
@Cooldown(60)
@CooldownMessage("You already have a pending marriage :no_entry:")
@Examples({ "marriage add @Shea#6653", "marriage add Shea", "marriage add 402557516728369153" })
public void add(Sx4CommandEvent event, @Argument(value = "user", endless = true) Member member) {
    User author = event.getAuthor();
    if (member.getUser().isBot()) {
        event.replyFailure("You cannot marry bots").queue();
        return;
    }
    Bson checkFilter = Filters.or(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", author.getIdLong()), Filters.eq("proposerId", member.getIdLong()), Filters.eq("partnerId", member.getIdLong()));
    List<Document> marriages = event.getMongo().getMarriages(checkFilter, Projections.include("partnerId", "proposerId")).into(new ArrayList<>());
    long userCount = marriages.stream().filter(d -> d.getLong("proposerId") == author.getIdLong() || d.getLong("partnerId") == author.getIdLong()).count();
    if (userCount >= 5) {
        event.removeCooldown();
        event.replyFailure("You cannot marry more than 5 users").queue();
        return;
    }
    long memberCount = marriages.stream().filter(d -> d.getLong("proposerId") == member.getIdLong() || d.getLong("partnerId") == member.getIdLong()).count();
    if (memberCount >= 5) {
        event.removeCooldown();
        event.replyFailure("That user is already married to 5 users").queue();
        return;
    }
    List<Button> buttons = List.of(Button.success("yes", "Yes"), Button.danger("no", "No"));
    event.reply(member.getAsMention() + ", **" + author.getName() + "** would like to marry you! Do you accept?").allowedMentions(EnumSet.of(Message.MentionType.USER)).setActionRow(buttons).submit().thenCompose(message -> {
        return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, member.getUser())).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, member.getUser())).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
    }).whenComplete((e, exception) -> {
        event.removeCooldown();
        Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
        if (cause instanceof CancelException) {
            GenericEvent cancelEvent = ((CancelException) cause).getEvent();
            if (cancelEvent != null) {
                ((ButtonClickEvent) cancelEvent).reply("Better luck next time " + author.getName() + " :broken_heart:").queue();
            }
            return;
        } else if (cause instanceof TimeoutException) {
            event.reply("Timed out :stopwatch:").queue();
            return;
        } else if (ExceptionUtility.sendExceptionally(event, exception)) {
            return;
        }
        Bson filter = Filters.or(Filters.and(Filters.eq("proposerId", member.getIdLong()), Filters.eq("partnerId", author.getIdLong())), Filters.and(Filters.eq("proposerId", author.getIdLong()), Filters.eq("partnerId", member.getIdLong())));
        event.getMongo().updateMarriage(filter, Updates.combine(Updates.setOnInsert("proposerId", author.getIdLong()), Updates.setOnInsert("partnerId", member.getIdLong()))).whenComplete((result, databaseException) -> {
            if (ExceptionUtility.sendExceptionally(event, databaseException)) {
                return;
            }
            if (result.getMatchedCount() != 0) {
                e.reply("You're already married to that user " + event.getConfig().getFailureEmote()).queue();
                return;
            }
            e.reply("You're now married to " + member.getAsMention() + " :tada: :heart:").queue();
        });
    });
}
Also used : Document(org.bson.Document) CancelException(com.sx4.bot.waiter.exception.CancelException) Command(com.jockie.bot.core.command.Command) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Projections(com.mongodb.client.model.Projections) Cooldown(com.jockie.bot.core.command.Command.Cooldown) CommandId(com.sx4.bot.annotations.command.CommandId) Member(net.dv8tion.jda.api.entities.Member) PagedResult(com.sx4.bot.paged.PagedResult) User(net.dv8tion.jda.api.entities.User) ArrayList(java.util.ArrayList) Filters(com.mongodb.client.model.Filters) Bson(org.bson.conversions.Bson) Redirects(com.sx4.bot.annotations.command.Redirects) Alternative(com.sx4.bot.entities.argument.Alternative) ButtonUtility(com.sx4.bot.utility.ButtonUtility) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Button(net.dv8tion.jda.api.interactions.components.Button) AlternativeOptions(com.sx4.bot.annotations.argument.AlternativeOptions) Waiter(com.sx4.bot.waiter.Waiter) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) ZoneOffset(java.time.ZoneOffset) EnumSet(java.util.EnumSet) Argument(com.jockie.bot.core.argument.Argument) Message(net.dv8tion.jda.api.entities.Message) Sx4Command(com.sx4.bot.core.Sx4Command) Updates(com.mongodb.client.model.Updates) CooldownMessage(com.sx4.bot.annotations.command.CooldownMessage) CompletionException(java.util.concurrent.CompletionException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) ModuleCategory(com.sx4.bot.category.ModuleCategory) List(java.util.List) Examples(com.sx4.bot.annotations.command.Examples) OffsetDateTime(java.time.OffsetDateTime) Sorts(com.mongodb.client.model.Sorts) DateTimeFormatter(java.time.format.DateTimeFormatter) StringJoiner(java.util.StringJoiner) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) User(net.dv8tion.jda.api.entities.User) Document(org.bson.Document) Bson(org.bson.conversions.Bson) Button(net.dv8tion.jda.api.interactions.components.Button) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) CompletionException(java.util.concurrent.CompletionException) CancelException(com.sx4.bot.waiter.exception.CancelException) Waiter(com.sx4.bot.waiter.Waiter) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) Redirects(com.sx4.bot.annotations.command.Redirects) Command(com.jockie.bot.core.command.Command) Sx4Command(com.sx4.bot.core.Sx4Command) Cooldown(com.jockie.bot.core.command.Command.Cooldown) CooldownMessage(com.sx4.bot.annotations.command.CooldownMessage) CommandId(com.sx4.bot.annotations.command.CommandId) Examples(com.sx4.bot.annotations.command.Examples)

Example 9 with ButtonClickEvent

use of net.dv8tion.jda.api.events.interaction.ButtonClickEvent in project Sx4 by sx4-discord-bot.

the class GuessTheNumberCommand method onCommand.

public void onCommand(Sx4CommandEvent event, @Argument(value = "user", endless = true) Member member, @Option(value = "min", description = "Choose the minimum number of the range") @Limit(min = 1) @DefaultNumber(1) int min, @Option(value = "max", description = "Choose the maximum number of the range") @Limit(min = 2) @DefaultNumber(50) int max) {
    User opponent = member.getUser();
    if (opponent.isBot()) {
        event.replyFailure("You cannot play against bots").queue();
        return;
    }
    if (opponent.getIdLong() == event.getAuthor().getIdLong()) {
        event.replyFailure("You cannot play against yourself").queue();
        return;
    }
    List<Button> buttons = List.of(Button.success("yes", "Yes"), Button.danger("no", "No"));
    event.reply(opponent.getAsMention() + ", do you want to play guess the number with **" + event.getAuthor().getName() + "**?").allowedMentions(EnumSet.of(Message.MentionType.USER)).setActionRow(buttons).submit().thenCompose(message -> {
        return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, opponent)).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, opponent)).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
    }).whenComplete((confirmEvent, confirmException) -> {
        Throwable confirmCause = confirmException instanceof CompletionException ? confirmException.getCause() : confirmException;
        if (confirmCause instanceof CancelException) {
            GenericEvent cancelEvent = ((CancelException) confirmCause).getEvent();
            if (cancelEvent != null) {
                ((ButtonClickEvent) cancelEvent).reply("Cancelled " + event.getConfig().getSuccessEmote()).queue();
            }
            return;
        } else if (confirmCause instanceof TimeoutException) {
            event.reply("Timed out :stopwatch:").queue();
            return;
        }
        confirmEvent.deferEdit().queue();
        CompletableFuture<MessageReceivedEvent> authorFuture = event.getAuthor().openPrivateChannel().submit().thenCompose(channel -> channel.sendMessage("Send a number between **" + min + "** and **" + max + "** or `cancel` to cancel").submit()).thenCompose(message -> {
            return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setUnique(event.getAuthor().getIdLong(), message.getChannel().getIdLong()).setTimeout(30).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setPredicate(e -> {
                int number;
                try {
                    number = Integer.parseInt(e.getMessage().getContentRaw());
                } catch (NumberFormatException exception) {
                    return false;
                }
                return number >= min && number <= max;
            }).start();
        });
        CompletableFuture<MessageReceivedEvent> opponentFuture = opponent.openPrivateChannel().submit().thenCompose(channel -> channel.sendMessage("Send a number between **" + min + "** and **" + max + "** or `cancel` to cancel").submit()).thenCompose(message -> {
            return new Waiter<>(event.getBot(), MessageReceivedEvent.class).setUnique(opponent.getIdLong(), message.getChannel().getIdLong()).setTimeout(30).setCancelPredicate(e -> e.getMessage().getContentRaw().equalsIgnoreCase("cancel")).setPredicate(e -> {
                int number;
                try {
                    number = Integer.parseInt(e.getMessage().getContentRaw());
                } catch (NumberFormatException exception) {
                    return false;
                }
                return number >= min && number <= max;
            }).start();
        });
        authorFuture.whenComplete((messageEvent, exception) -> {
            Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
            if (cause instanceof CancelException) {
                opponentFuture.cancel(true);
                if (((CancelException) cause).getType() == CancelType.USER) {
                    event.getAuthor().openPrivateChannel().flatMap(channel -> channel.sendMessage("Cancelled " + event.getConfig().getSuccessEmote())).queue();
                }
                event.replyFailure("**" + event.getAuthor().getAsTag() + "** cancelled their response").queue();
                return;
            } else if (cause instanceof TimeoutException) {
                opponentFuture.cancel(true);
                event.replyFailure("**" + event.getAuthor().getAsTag() + "** took too long to respond").queue();
                return;
            } else if (cause instanceof ErrorResponseException) {
                opponentFuture.cancel(true);
                event.replyFailure("I could not send a message to **" + event.getAuthor().getAsTag() + "**").queue();
                return;
            }
            messageEvent.getChannel().sendMessage("Your number has been received, results will be sent in " + event.getTextChannel().getAsMention()).queue();
        });
        opponentFuture.whenComplete((messageEvent, exception) -> {
            Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
            if (cause instanceof CancelException) {
                authorFuture.cancel(true);
                if (((CancelException) cause).getType() == CancelType.USER) {
                    opponent.openPrivateChannel().flatMap(channel -> channel.sendMessage("Cancelled " + event.getConfig().getSuccessEmote())).queue();
                }
                event.replyFailure("**" + opponent.getAsTag() + "** cancelled their response").queue();
                return;
            } else if (cause instanceof TimeoutException) {
                authorFuture.cancel(true);
                event.replyFailure("**" + opponent.getAsTag() + "** took too long to respond").queue();
                return;
            } else if (cause instanceof ErrorResponseException) {
                authorFuture.cancel(true);
                event.replyFailure("I could not send a message to **" + opponent.getAsTag() + "**").queue();
                return;
            }
            messageEvent.getChannel().sendMessage("Your number has been received, results will be sent in " + event.getTextChannel().getAsMention()).queue();
        });
        CompletableFuture.allOf(authorFuture, opponentFuture).whenComplete((result, exception) -> {
            if (exception != null) {
                return;
            }
            MessageReceivedEvent authorEvent = authorFuture.join(), opponentEvent = opponentFuture.join();
            ObjectId gameId = ObjectId.get();
            int authorNumber = Integer.parseInt(authorEvent.getMessage().getContentRaw());
            int opponentNumber = Integer.parseInt(opponentEvent.getMessage().getContentRaw());
            int randomNumber = event.getRandom().nextInt(max) + 1;
            Document authorData = new Document("userId", event.getAuthor().getIdLong()).append("gameId", gameId).append("type", GameType.GUESS_THE_NUMBER.getId()).append("choice", authorNumber).append("answer", randomNumber);
            Document opponentData = new Document("userId", opponent.getIdLong()).append("gameId", gameId).append("type", GameType.GUESS_THE_NUMBER.getId()).append("choice", authorNumber).append("answer", randomNumber);
            int authorDifference = Math.abs(authorNumber - randomNumber), opponentDifference = Math.abs(opponentNumber - randomNumber);
            StringBuilder content = new StringBuilder("The random number was **" + randomNumber + "**\n" + opponent.getName() + "'s number was **" + opponentNumber + "**\n" + event.getAuthor().getName() + "'s number was **" + authorNumber + "**\n\n");
            if (authorDifference == opponentDifference) {
                content.append("You both guessed the same number, It was a draw!");
                authorData.append("state", GameState.DRAW.getId());
                opponentData.append("state", GameState.DRAW.getId());
            } else if (authorDifference > opponentDifference) {
                content.append(opponent.getName()).append(" won! They were the closest to ").append(randomNumber);
                authorData.append("state", GameState.LOSS.getId());
                opponentData.append("state", GameState.WIN.getId());
            } else {
                content.append(event.getAuthor().getName()).append(" won! They were the closest to ").append(randomNumber);
                authorData.append("state", GameState.WIN.getId());
                opponentData.append("state", GameState.LOSS.getId());
            }
            event.reply(content.toString()).queue();
            event.getMongo().insertManyGames(List.of(authorData, opponentData)).whenComplete(MongoDatabase.exceptionally());
        });
    });
}
Also used : Document(org.bson.Document) CancelException(com.sx4.bot.waiter.exception.CancelException) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) Member(net.dv8tion.jda.api.entities.Member) User(net.dv8tion.jda.api.entities.User) ButtonUtility(com.sx4.bot.utility.ButtonUtility) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Button(net.dv8tion.jda.api.interactions.components.Button) Option(com.jockie.bot.core.option.Option) Waiter(com.sx4.bot.waiter.Waiter) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) GameState(com.sx4.bot.entities.games.GameState) EnumSet(java.util.EnumSet) Argument(com.jockie.bot.core.argument.Argument) Limit(com.sx4.bot.annotations.argument.Limit) CancelType(com.sx4.bot.waiter.Waiter.CancelType) Message(net.dv8tion.jda.api.entities.Message) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) Sx4Command(com.sx4.bot.core.Sx4Command) CompletionException(java.util.concurrent.CompletionException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) GameType(com.sx4.bot.entities.games.GameType) ModuleCategory(com.sx4.bot.category.ModuleCategory) List(java.util.List) DefaultNumber(com.sx4.bot.annotations.argument.DefaultNumber) ObjectId(org.bson.types.ObjectId) MessageReceivedEvent(net.dv8tion.jda.api.events.message.MessageReceivedEvent) User(net.dv8tion.jda.api.entities.User) ObjectId(org.bson.types.ObjectId) Document(org.bson.Document) MessageReceivedEvent(net.dv8tion.jda.api.events.message.MessageReceivedEvent) Button(net.dv8tion.jda.api.interactions.components.Button) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) CompletionException(java.util.concurrent.CompletionException) ErrorResponseException(net.dv8tion.jda.api.exceptions.ErrorResponseException) CancelException(com.sx4.bot.waiter.exception.CancelException) Waiter(com.sx4.bot.waiter.Waiter) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException)

Example 10 with ButtonClickEvent

use of net.dv8tion.jda.api.events.interaction.ButtonClickEvent in project Sx4 by sx4-discord-bot.

the class FakePermissionsCommand method delete.

@Command(value = "delete", aliases = { "remove" }, description = "Deletes fake permissions for a user or role")
@CommandId(172)
@Examples({ "fake permissions delete @Shea#6653", "fake permissions delete @Mods", "fake permissions delete all" })
@AuthorPermissions(permissions = { Permission.ADMINISTRATOR })
public void delete(Sx4CommandEvent event, @Argument(value = "user | role | all", endless = true, nullDefault = true) @AlternativeOptions("all") Alternative<IPermissionHolder> option) {
    if (option == null) {
        List<Document> fakePermissions = event.getProperty("fakePermissions");
        if (fakePermissions.isEmpty()) {
            event.replyFailure("Nothing has fake permissions in this server").queue();
            return;
        }
        PagedResult<Document> paged = new PagedResult<>(event.getBot(), fakePermissions).setAuthor("User & Roles", null, event.getGuild().getIconUrl()).setTimeout(60).setDisplayFunction(data -> {
            int type = data.getInteger("type");
            long id = data.getLong("id");
            if (type == HolderType.USER.getType()) {
                User user = event.getShardManager().getUserById(id);
                return user == null ? "Anonymous#0000 (" + id + ")" : user.getAsTag();
            } else {
                Role role = event.getGuild().getRoleById(id);
                return role == null ? "Deleted Role (" + id + ")" : role.getAsMention();
            }
        });
        paged.onTimeout(() -> event.reply("Timed out :stopwatch:").queue());
        paged.onSelect(select -> {
            Document data = select.getSelected();
            boolean isRole = data.getInteger("type") == HolderType.ROLE.getType();
            long id = data.getLong("id");
            User user = isRole ? null : event.getShardManager().getUserById(id);
            Role role = isRole ? event.getGuild().getRoleById(id) : null;
            event.getMongo().updateGuildById(event.getGuild().getIdLong(), Updates.pull("fakePermissions.holders", Filters.eq("id", id))).whenComplete((result, exception) -> {
                if (ExceptionUtility.sendExceptionally(event, exception)) {
                    return;
                }
                if (result.getModifiedCount() == 0) {
                    event.replyFailure("That " + (isRole ? "role" : "user") + " doesn't have any fake permissions").queue();
                    return;
                }
                event.replySuccess((isRole ? (role == null ? "Deleted Role (" + id + ")" : role.getAsMention()) : "**" + (user == null ? "Anonymous#0000** (" + id + ")" : user.getAsTag() + "**")) + " no longer has any fake permissions").queue();
            });
        });
        paged.execute(event);
    } else if (option.isAlternative()) {
        List<Button> buttons = List.of(Button.success("yes", "Yes"), Button.danger("no", "No"));
        event.reply(event.getAuthor().getName() + ", are you sure you want to delete **all** fake permissions data?").setActionRow(buttons).submit().thenCompose(message -> {
            return new Waiter<>(event.getBot(), ButtonClickEvent.class).setPredicate(e -> ButtonUtility.handleButtonConfirmation(e, message, event.getAuthor())).setCancelPredicate(e -> ButtonUtility.handleButtonCancellation(e, message, event.getAuthor())).onFailure(e -> ButtonUtility.handleButtonFailure(e, message)).setTimeout(60).start();
        }).whenComplete((e, exception) -> {
            Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
            if (cause instanceof CancelException) {
                GenericEvent cancelEvent = ((CancelException) cause).getEvent();
                if (cancelEvent != null) {
                    ((ButtonClickEvent) cancelEvent).reply("Cancelled " + event.getConfig().getSuccessEmote()).queue();
                }
                return;
            } else if (cause instanceof TimeoutException) {
                event.reply("Timed out :stopwatch:").queue();
                return;
            } else if (ExceptionUtility.sendExceptionally(event, exception)) {
                return;
            }
            event.getMongo().updateGuildById(event.getGuild().getIdLong(), Updates.unset("fakePermissions.holders")).whenComplete((result, databaseException) -> {
                if (ExceptionUtility.sendExceptionally(event, databaseException)) {
                    return;
                }
                e.reply("All fake permission data has been deleted in this server " + event.getConfig().getSuccessEmote()).queue();
            });
        });
    } else {
        IPermissionHolder holder = option.getValue();
        boolean role = holder instanceof Role;
        event.getMongo().updateGuildById(event.getGuild().getIdLong(), Updates.pull("fakePermissions.holders", Filters.eq("id", holder.getIdLong()))).whenComplete((result, exception) -> {
            if (ExceptionUtility.sendExceptionally(event, exception)) {
                return;
            }
            if (result.getModifiedCount() == 0) {
                event.replyFailure("That " + (role ? "role" : "user") + " doesn't have any fake permissions").queue();
                return;
            }
            event.replySuccess((role ? ((Role) holder).getAsMention() : "**" + ((Member) holder).getUser().getAsTag() + "**") + " no longer has any fake permissions").queue();
        });
    }
}
Also used : HolderType(com.sx4.bot.entities.settings.HolderType) Document(org.bson.Document) Arrays(java.util.Arrays) CancelException(com.sx4.bot.waiter.exception.CancelException) Command(com.jockie.bot.core.command.Command) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Permission(net.dv8tion.jda.api.Permission) Projections(com.mongodb.client.model.Projections) CommandId(com.sx4.bot.annotations.command.CommandId) Member(net.dv8tion.jda.api.entities.Member) PagedResult(com.sx4.bot.paged.PagedResult) User(net.dv8tion.jda.api.entities.User) Filters(com.mongodb.client.model.Filters) Bson(org.bson.conversions.Bson) Alternative(com.sx4.bot.entities.argument.Alternative) ButtonUtility(com.sx4.bot.utility.ButtonUtility) Role(net.dv8tion.jda.api.entities.Role) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Button(net.dv8tion.jda.api.interactions.components.Button) AlternativeOptions(com.sx4.bot.annotations.argument.AlternativeOptions) Waiter(com.sx4.bot.waiter.Waiter) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) Argument(com.jockie.bot.core.argument.Argument) AuthorPermissions(com.sx4.bot.annotations.command.AuthorPermissions) Operators(com.sx4.bot.database.mongo.model.Operators) Sx4Command(com.sx4.bot.core.Sx4Command) Predicate(java.util.function.Predicate) Updates(com.mongodb.client.model.Updates) CompletionException(java.util.concurrent.CompletionException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Collectors(java.util.stream.Collectors) ModuleCategory(com.sx4.bot.category.ModuleCategory) List(java.util.List) Examples(com.sx4.bot.annotations.command.Examples) IPermissionHolder(net.dv8tion.jda.api.entities.IPermissionHolder) ExceptionUtility(com.sx4.bot.utility.ExceptionUtility) Comparator(java.util.Comparator) Collections(java.util.Collections) User(net.dv8tion.jda.api.entities.User) ButtonClickEvent(net.dv8tion.jda.api.events.interaction.ButtonClickEvent) Document(org.bson.Document) IPermissionHolder(net.dv8tion.jda.api.entities.IPermissionHolder) Role(net.dv8tion.jda.api.entities.Role) GenericEvent(net.dv8tion.jda.api.events.GenericEvent) CompletionException(java.util.concurrent.CompletionException) List(java.util.List) CancelException(com.sx4.bot.waiter.exception.CancelException) TimeoutException(com.sx4.bot.waiter.exception.TimeoutException) AuthorPermissions(com.sx4.bot.annotations.command.AuthorPermissions) Command(com.jockie.bot.core.command.Command) Sx4Command(com.sx4.bot.core.Sx4Command) CommandId(com.sx4.bot.annotations.command.CommandId) Examples(com.sx4.bot.annotations.command.Examples)

Aggregations

ButtonClickEvent (net.dv8tion.jda.api.events.interaction.ButtonClickEvent)19 Button (net.dv8tion.jda.api.interactions.components.Button)18 Argument (com.jockie.bot.core.argument.Argument)16 ModuleCategory (com.sx4.bot.category.ModuleCategory)16 Sx4Command (com.sx4.bot.core.Sx4Command)16 Sx4CommandEvent (com.sx4.bot.core.Sx4CommandEvent)16 Waiter (com.sx4.bot.waiter.Waiter)16 CancelException (com.sx4.bot.waiter.exception.CancelException)16 TimeoutException (com.sx4.bot.waiter.exception.TimeoutException)16 CompletionException (java.util.concurrent.CompletionException)16 GenericEvent (net.dv8tion.jda.api.events.GenericEvent)16 Document (org.bson.Document)16 List (java.util.List)15 User (net.dv8tion.jda.api.entities.User)15 Command (com.jockie.bot.core.command.Command)14 PagedResult (com.sx4.bot.paged.PagedResult)14 ButtonUtility (com.sx4.bot.utility.ButtonUtility)14 AlternativeOptions (com.sx4.bot.annotations.argument.AlternativeOptions)13 Alternative (com.sx4.bot.entities.argument.Alternative)13 ExceptionUtility (com.sx4.bot.utility.ExceptionUtility)13