Search in sources :

Example 1 with TimeAction

use of com.sx4.bot.entities.mod.action.TimeAction in project Sx4 by sx4-discord-bot.

the class ModUtility method mute.

public static CompletableFuture<TimeAction> mute(Sx4 bot, Member target, Member moderator, Duration time, boolean extend, Reason reason) {
    Guild guild = target.getGuild();
    long guildId = guild.getIdLong(), userId = target.getIdLong();
    Document mute = bot.getMongo().getGuildById(guildId, Projections.include("mute.roleId", "mute.defaultTime", "mute.autoUpdate")).get("mute", MongoDatabase.EMPTY_DOCUMENT);
    long duration = time == null ? mute.get("defaultTime", ModUtility.DEFAULT_MUTE_DURATION) : time.toSeconds();
    AtomicReference<Role> atomicRole = new AtomicReference<>();
    return ModUtility.upsertMuteRole(bot.getMongo(), guild, mute.get("roleId", 0L), mute.get("autoUpdate", true)).thenCompose(role -> {
        if (!guild.getSelfMember().hasPermission(Permission.MANAGE_ROLES)) {
            throw new BotPermissionException(Permission.MANAGE_ROLES);
        }
        if (!guild.getSelfMember().canInteract(role)) {
            throw new BotHierarchyException("mute");
        }
        atomicRole.set(role);
        List<Bson> update = List.of(Operators.set("unmuteAt", Operators.add(duration, Operators.cond(Operators.and(extend, Operators.exists("$unmuteAt")), "$unmuteAt", Operators.nowEpochSecond()))));
        Bson filter = Filters.and(Filters.eq("userId", userId), Filters.eq("guildId", guildId));
        return bot.getMongo().updateMute(filter, update, new UpdateOptions().upsert(true));
    }).thenCompose(result -> {
        Role role = atomicRole.get();
        boolean wasExtended = extend && result.getUpsertedId() == null;
        return guild.addRoleToMember(target, role).reason(ModUtility.getAuditReason(reason, moderator.getUser())).submit().thenApply($ -> {
            bot.getMuteManager().putMute(guild.getIdLong(), target.getIdLong(), role.getIdLong(), duration, wasExtended);
            ModActionEvent modEvent = wasExtended ? new MuteExtendEvent(moderator, target.getUser(), reason, duration) : new MuteEvent(moderator, target.getUser(), reason, duration);
            bot.getModActionManager().onModAction(modEvent);
            return new TimeAction(wasExtended ? ModAction.MUTE_EXTEND : ModAction.MUTE, duration);
        });
    });
}
Also used : Document(org.bson.Document) Operators(com.sx4.bot.database.mongo.model.Operators) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) com.sx4.bot.entities.mod.action(com.sx4.bot.entities.mod.action) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) MaxRolesException(com.sx4.bot.exceptions.mod.MaxRolesException) Member(net.dv8tion.jda.api.entities.Member) AuthorPermissionException(com.sx4.bot.exceptions.mod.AuthorPermissionException) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) AtomicReference(java.util.concurrent.atomic.AtomicReference) User(net.dv8tion.jda.api.entities.User) Bson(org.bson.conversions.Bson) List(java.util.List) Guild(net.dv8tion.jda.api.entities.Guild) Sx4(com.sx4.bot.core.Sx4) Role(net.dv8tion.jda.api.entities.Role) Duration(java.time.Duration) Reason(com.sx4.bot.entities.mod.Reason) Clock(java.time.Clock) com.sx4.bot.events.mod(com.sx4.bot.events.mod) com.mongodb.client.model(com.mongodb.client.model) Collections(java.util.Collections) AtomicReference(java.util.concurrent.atomic.AtomicReference) Guild(net.dv8tion.jda.api.entities.Guild) Document(org.bson.Document) Bson(org.bson.conversions.Bson) Role(net.dv8tion.jda.api.entities.Role) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) List(java.util.List)

Example 2 with TimeAction

use of com.sx4.bot.entities.mod.action.TimeAction in project Sx4 by sx4-discord-bot.

the class ModUtility method performAction.

public static CompletableFuture<? extends Action> performAction(Sx4 bot, Action action, Member target, Member moderator, Reason reason) {
    Guild guild = target.getGuild();
    switch(action.getModAction()) {
        case WARN:
            return ModUtility.warn(bot, target, moderator, reason);
        case MUTE:
        case MUTE_EXTEND:
            if (!guild.getSelfMember().hasPermission(Permission.MANAGE_ROLES)) {
                return CompletableFuture.failedFuture(new BotPermissionException(Permission.MANAGE_ROLES));
            }
            return ModUtility.mute(bot, target, moderator, Duration.ofSeconds(((TimeAction) action).getDuration()), action.getModAction().isExtend(), reason);
        case KICK:
            if (!guild.getSelfMember().hasPermission(Permission.KICK_MEMBERS)) {
                return CompletableFuture.failedFuture(new BotPermissionException(Permission.KICK_MEMBERS));
            }
            if (!guild.getSelfMember().canInteract(target)) {
                return CompletableFuture.failedFuture(new BotHierarchyException("kick"));
            }
            if (!moderator.hasPermission(Permission.KICK_MEMBERS)) {
                return CompletableFuture.failedFuture(new AuthorPermissionException(Permission.KICK_MEMBERS));
            }
            return target.kick(ModUtility.getAuditReason(reason, moderator.getUser())).submit().thenApply($ -> {
                bot.getModActionManager().onModAction(new KickEvent(moderator, target.getUser(), reason));
                return action;
            });
        case TEMPORARY_BAN:
            if (!guild.getSelfMember().hasPermission(Permission.BAN_MEMBERS)) {
                return CompletableFuture.failedFuture(new BotPermissionException(Permission.BAN_MEMBERS));
            }
            if (!guild.getSelfMember().canInteract(target)) {
                return CompletableFuture.failedFuture(new BotHierarchyException("ban"));
            }
            if (!moderator.hasPermission(Permission.BAN_MEMBERS)) {
                return CompletableFuture.failedFuture(new AuthorPermissionException(Permission.BAN_MEMBERS));
            }
            long temporaryBanDuration = ((TimeAction) action).getDuration();
            List<Bson> temporaryBanUpdate = List.of(Operators.set("unbanAt", Operators.add(Operators.nowEpochSecond(), temporaryBanDuration)));
            Bson filter = Filters.and(Filters.eq("userId", target.getIdLong()), Filters.eq("guildId", guild.getIdLong()));
            return bot.getMongo().updateTemporaryBan(filter, temporaryBanUpdate, new UpdateOptions().upsert(true)).thenCompose(temporaryBanResult -> target.ban(1).reason(ModUtility.getAuditReason(reason, moderator.getUser())).submit()).thenApply($ -> {
                bot.getModActionManager().onModAction(new TemporaryBanEvent(moderator, target.getUser(), reason, true, temporaryBanDuration));
                bot.getTemporaryBanManager().putBan(guild.getIdLong(), target.getIdLong(), temporaryBanDuration);
                return action;
            });
        case BAN:
            if (!guild.getSelfMember().hasPermission(Permission.BAN_MEMBERS)) {
                return CompletableFuture.failedFuture(new BotPermissionException(Permission.BAN_MEMBERS));
            }
            if (!guild.getSelfMember().canInteract(target)) {
                return CompletableFuture.failedFuture(new BotHierarchyException("ban"));
            }
            if (!moderator.hasPermission(Permission.BAN_MEMBERS)) {
                return CompletableFuture.failedFuture(new AuthorPermissionException(Permission.BAN_MEMBERS));
            }
            return target.ban(1).reason(ModUtility.getAuditReason(reason, moderator.getUser())).submit().thenApply($ -> {
                bot.getModActionManager().onModAction(new BanEvent(moderator, target.getUser(), reason, true));
                return action;
            });
        default:
            return CompletableFuture.completedFuture(null);
    }
}
Also used : Document(org.bson.Document) Operators(com.sx4.bot.database.mongo.model.Operators) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) com.sx4.bot.entities.mod.action(com.sx4.bot.entities.mod.action) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) MaxRolesException(com.sx4.bot.exceptions.mod.MaxRolesException) Member(net.dv8tion.jda.api.entities.Member) AuthorPermissionException(com.sx4.bot.exceptions.mod.AuthorPermissionException) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) AtomicReference(java.util.concurrent.atomic.AtomicReference) User(net.dv8tion.jda.api.entities.User) Bson(org.bson.conversions.Bson) List(java.util.List) Guild(net.dv8tion.jda.api.entities.Guild) Sx4(com.sx4.bot.core.Sx4) Role(net.dv8tion.jda.api.entities.Role) Duration(java.time.Duration) Reason(com.sx4.bot.entities.mod.Reason) Clock(java.time.Clock) com.sx4.bot.events.mod(com.sx4.bot.events.mod) com.mongodb.client.model(com.mongodb.client.model) Collections(java.util.Collections) Guild(net.dv8tion.jda.api.entities.Guild) Bson(org.bson.conversions.Bson) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) AuthorPermissionException(com.sx4.bot.exceptions.mod.AuthorPermissionException)

Example 3 with TimeAction

use of com.sx4.bot.entities.mod.action.TimeAction in project Sx4 by sx4-discord-bot.

the class ModUtility method warn.

public static CompletableFuture<WarnAction> warn(Sx4 bot, Member target, Member moderator, Reason reason) {
    CompletableFuture<WarnAction> future = new CompletableFuture<>();
    Guild guild = target.getGuild();
    Document data = bot.getMongo().getGuildById(guild.getIdLong(), Projections.include("warn", "mute", "temporaryBan", "fakePermissions"));
    List<Document> fakePermissions = data.getEmbedded(List.of("fakePermissions", "holders"), Collections.emptyList());
    Document warnData = data.get("warn", MongoDatabase.EMPTY_DOCUMENT);
    List<Document> config = warnData.getList("config", Document.class, Warn.DEFAULT_CONFIG);
    boolean punishments = warnData.getBoolean("punishments", true);
    Document reset = warnData.get("reset", Document.class);
    int maxWarning = punishments ? config.stream().map(d -> d.getInteger("number")).max(Integer::compareTo).get() : Integer.MAX_VALUE;
    List<Bson> update = List.of(Operators.set("warnings", Operators.let(new Document("warnings", Operators.ifNull("$warnings", 0)), Operators.mod(Operators.cond(Operators.exists("$reset"), Operators.max(1, Operators.add(1, Operators.subtract("$$warnings", Operators.multiply(Operators.toInt(Operators.floor(Operators.divide(Operators.subtract(Operators.nowEpochSecond(), "$lastWarning"), "$reset.after"))), "$reset.amount")))), Operators.add("$$warnings", 1)), maxWarning))), Operators.set("lastWarning", Operators.nowEpochSecond()), reset == null ? Operators.unset("reset") : Operators.set("reset", reset));
    FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER).projection(Projections.include("warnings")).upsert(true);
    Bson filter = Filters.and(Filters.eq("userId", target.getIdLong()), Filters.eq("guildId", guild.getIdLong()));
    bot.getMongo().findAndUpdateWarnings(filter, update, options).whenComplete((result, exception) -> {
        if (exception != null) {
            future.completeExceptionally(exception);
            return;
        }
        int warnings = result.getInteger("warnings");
        Action warnAction = new Action(ModAction.WARN);
        Action currentAction = warnAction, nextAction = warnAction;
        if (punishments) {
            for (Document configData : config) {
                int number = configData.getInteger("number");
                if (number == warnings) {
                    currentAction = Action.fromData(configData.get("action", Document.class));
                } else if (number == warnings + 1) {
                    nextAction = Action.fromData(configData.get("action", Document.class));
                }
            }
        }
        Action action = currentAction;
        Warn currentWarning = new Warn(action, warnings);
        Warn nextWarning = new Warn(nextAction, warnings + 1);
        switch(action.getModAction()) {
            case WARN:
                bot.getModActionManager().onModAction(new WarnEvent(moderator, target.getUser(), reason, currentWarning, nextWarning));
                future.complete(new WarnAction(currentWarning));
                break;
            case MUTE_EXTEND:
            case MUTE:
                if (!guild.getSelfMember().hasPermission(Permission.MANAGE_ROLES)) {
                    future.completeExceptionally(new BotPermissionException(Permission.MANAGE_ROLES));
                    return;
                }
                AtomicReference<Role> atomicRole = new AtomicReference<>();
                Document mute = data.get("mute", MongoDatabase.EMPTY_DOCUMENT);
                long muteDuration = ((TimeAction) action).getDuration();
                boolean extend = action.getModAction().isExtend();
                ModUtility.upsertMuteRole(bot.getMongo(), guild, mute.get("roleId", 0L), mute.get("autoUpdate", true)).thenCompose(role -> {
                    atomicRole.set(role);
                    List<Bson> muteUpdate = List.of(Operators.set("unmuteAt", Operators.add(muteDuration, Operators.cond(Operators.and(extend, Operators.exists("$unmuteAt")), "$unmuteAt", Operators.nowEpochSecond()))));
                    Bson muteFilter = Filters.and(Filters.eq("userId", target.getIdLong()), Filters.eq("guildId", guild.getIdLong()));
                    return bot.getMongo().updateMute(muteFilter, muteUpdate, new UpdateOptions().upsert(true));
                }).whenComplete((muteResult, muteException) -> {
                    if (muteException != null) {
                        future.completeExceptionally(muteException);
                        return;
                    }
                    Role role = atomicRole.get();
                    guild.addRoleToMember(target, role).reason(ModUtility.getAuditReason(reason, moderator.getUser())).queue($ -> {
                        bot.getMuteManager().putMute(guild.getIdLong(), target.getIdLong(), role.getIdLong(), muteDuration, extend && muteResult.getUpsertedId() == null);
                        bot.getModActionManager().onModAction(new WarnEvent(moderator, target.getUser(), reason, currentWarning, nextWarning));
                        future.complete(new WarnAction(currentWarning));
                    });
                });
                break;
            case KICK:
                if (!guild.getSelfMember().hasPermission(Permission.KICK_MEMBERS)) {
                    future.completeExceptionally(new BotPermissionException(Permission.KICK_MEMBERS));
                    return;
                }
                if (!guild.getSelfMember().canInteract(target)) {
                    future.completeExceptionally(new BotHierarchyException("kick"));
                    return;
                }
                if (!CheckUtility.hasPermissions(bot, moderator, fakePermissions, Permission.KICK_MEMBERS)) {
                    future.completeExceptionally(new AuthorPermissionException(Permission.KICK_MEMBERS));
                    return;
                }
                target.kick(ModUtility.getAuditReason(reason, moderator.getUser())).queue($ -> {
                    bot.getModActionManager().onModAction(new WarnEvent(moderator, target.getUser(), reason, currentWarning, nextWarning));
                    future.complete(new WarnAction(currentWarning));
                });
                break;
            case TEMPORARY_BAN:
                if (!guild.getSelfMember().hasPermission(Permission.BAN_MEMBERS)) {
                    future.completeExceptionally(new BotPermissionException(Permission.BAN_MEMBERS));
                    return;
                }
                if (!guild.getSelfMember().canInteract(target)) {
                    future.completeExceptionally(new BotHierarchyException("ban"));
                    return;
                }
                if (!CheckUtility.hasPermissions(bot, moderator, fakePermissions, Permission.BAN_MEMBERS)) {
                    future.completeExceptionally(new AuthorPermissionException(Permission.BAN_MEMBERS));
                    return;
                }
                long temporaryBanDuration = ((TimeAction) action).getDuration();
                Bson temporaryBanUpdate = Updates.set("unbanAt", Clock.systemUTC().instant().getEpochSecond() + temporaryBanDuration);
                Bson temporaryBanFilter = Filters.and(Filters.eq("userId", target.getIdLong()), Filters.eq("guildId", guild.getIdLong()));
                bot.getMongo().updateTemporaryBan(temporaryBanFilter, temporaryBanUpdate, new UpdateOptions().upsert(true)).whenComplete((temporaryBanResult, temporaryBanException) -> {
                    if (temporaryBanException != null) {
                        future.completeExceptionally(temporaryBanException);
                        return;
                    }
                    target.ban(1).reason(ModUtility.getAuditReason(reason, moderator.getUser())).queue($ -> {
                        bot.getModActionManager().onModAction(new WarnEvent(moderator, target.getUser(), reason, currentWarning, nextWarning));
                        bot.getTemporaryBanManager().putBan(guild.getIdLong(), target.getIdLong(), ((TimeAction) action).getDuration());
                        future.complete(new WarnAction(currentWarning));
                    });
                });
                break;
            case BAN:
                if (!guild.getSelfMember().hasPermission(Permission.BAN_MEMBERS)) {
                    future.completeExceptionally(new BotPermissionException(Permission.BAN_MEMBERS));
                    return;
                }
                if (!guild.getSelfMember().canInteract(target)) {
                    future.completeExceptionally(new BotHierarchyException("ban"));
                    return;
                }
                if (!CheckUtility.hasPermissions(bot, moderator, fakePermissions, Permission.BAN_MEMBERS)) {
                    future.completeExceptionally(new AuthorPermissionException(Permission.BAN_MEMBERS));
                    return;
                }
                target.ban(1).reason(ModUtility.getAuditReason(reason, moderator.getUser())).queue($ -> {
                    bot.getModActionManager().onModAction(new WarnEvent(moderator, target.getUser(), reason, currentWarning, nextWarning));
                    future.complete(new WarnAction(currentWarning));
                });
                break;
            default:
                break;
        }
    });
    return future;
}
Also used : Document(org.bson.Document) Operators(com.sx4.bot.database.mongo.model.Operators) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) com.sx4.bot.entities.mod.action(com.sx4.bot.entities.mod.action) Permission(net.dv8tion.jda.api.Permission) MongoDatabase(com.sx4.bot.database.mongo.MongoDatabase) CompletableFuture(java.util.concurrent.CompletableFuture) MaxRolesException(com.sx4.bot.exceptions.mod.MaxRolesException) Member(net.dv8tion.jda.api.entities.Member) AuthorPermissionException(com.sx4.bot.exceptions.mod.AuthorPermissionException) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) AtomicReference(java.util.concurrent.atomic.AtomicReference) User(net.dv8tion.jda.api.entities.User) Bson(org.bson.conversions.Bson) List(java.util.List) Guild(net.dv8tion.jda.api.entities.Guild) Sx4(com.sx4.bot.core.Sx4) Role(net.dv8tion.jda.api.entities.Role) Duration(java.time.Duration) Reason(com.sx4.bot.entities.mod.Reason) Clock(java.time.Clock) com.sx4.bot.events.mod(com.sx4.bot.events.mod) com.mongodb.client.model(com.mongodb.client.model) Collections(java.util.Collections) Guild(net.dv8tion.jda.api.entities.Guild) Document(org.bson.Document) Bson(org.bson.conversions.Bson) CompletableFuture(java.util.concurrent.CompletableFuture) BotPermissionException(com.sx4.bot.exceptions.mod.BotPermissionException) List(java.util.List) BotHierarchyException(com.sx4.bot.exceptions.mod.BotHierarchyException) AuthorPermissionException(com.sx4.bot.exceptions.mod.AuthorPermissionException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Role(net.dv8tion.jda.api.entities.Role)

Example 4 with TimeAction

use of com.sx4.bot.entities.mod.action.TimeAction in project Sx4 by sx4-discord-bot.

the class WarnCommand method onCommand.

public void onCommand(Sx4CommandEvent event, @Argument(value = "user") Member member, @Argument(value = "reason", endless = true, nullDefault = true) Reason reason) {
    if (member.getIdLong() == event.getSelfUser().getIdLong()) {
        event.replyFailure("You cannot warn me, that is illegal").queue();
        return;
    }
    if (!event.getMember().canInteract(member)) {
        event.replyFailure("You cannot warn someone higher or equal than your top role").queue();
        return;
    }
    ModUtility.warn(event.getBot(), member, event.getMember(), reason).whenComplete((warning, exception) -> {
        Throwable cause = exception instanceof CompletionException ? exception.getCause() : exception;
        if (cause != null) {
            event.replyFailure(cause.getMessage()).queue();
            return;
        }
        Warn warn = warning.getWarning();
        Action action = warn.getAction();
        event.replyFormat("**%s** has received a %s%s (%s warning) " + event.getConfig().getSuccessEmote(), member.getUser().getAsTag(), action.getModAction().getName().toLowerCase(), action instanceof TimeAction ? " for " + TimeUtility.LONG_TIME_FORMATTER.parse(((TimeAction) action).getDuration()) : "", NumberUtility.getSuffixed(warn.getNumber())).queue();
    });
}
Also used : ModAction(com.sx4.bot.entities.mod.action.ModAction) TimeAction(com.sx4.bot.entities.mod.action.TimeAction) Action(com.sx4.bot.entities.mod.action.Action) CompletionException(java.util.concurrent.CompletionException) TimeAction(com.sx4.bot.entities.mod.action.TimeAction) Warn(com.sx4.bot.entities.mod.action.Warn)

Aggregations

com.mongodb.client.model (com.mongodb.client.model)3 Sx4 (com.sx4.bot.core.Sx4)3 MongoDatabase (com.sx4.bot.database.mongo.MongoDatabase)3 Operators (com.sx4.bot.database.mongo.model.Operators)3 Reason (com.sx4.bot.entities.mod.Reason)3 com.sx4.bot.entities.mod.action (com.sx4.bot.entities.mod.action)3 com.sx4.bot.events.mod (com.sx4.bot.events.mod)3 AuthorPermissionException (com.sx4.bot.exceptions.mod.AuthorPermissionException)3 BotHierarchyException (com.sx4.bot.exceptions.mod.BotHierarchyException)3 BotPermissionException (com.sx4.bot.exceptions.mod.BotPermissionException)3 MaxRolesException (com.sx4.bot.exceptions.mod.MaxRolesException)3 Clock (java.time.Clock)3 Duration (java.time.Duration)3 Collections (java.util.Collections)3 List (java.util.List)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 Permission (net.dv8tion.jda.api.Permission)3 Guild (net.dv8tion.jda.api.entities.Guild)3 Member (net.dv8tion.jda.api.entities.Member)3