diff --git a/src/main/java/com/jagrosh/vortex/Listener.java b/src/main/java/com/jagrosh/vortex/Listener.java index 7255b9b..8006418 100644 --- a/src/main/java/com/jagrosh/vortex/Listener.java +++ b/src/main/java/com/jagrosh/vortex/Listener.java @@ -24,6 +24,7 @@ import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.ReadyEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateSlowmodeEvent; import net.dv8tion.jda.api.events.guild.GuildBanEvent; import net.dv8tion.jda.api.events.guild.GuildUnbanEvent; import net.dv8tion.jda.api.events.guild.member.*; @@ -207,6 +208,10 @@ if(!gevent.getMember().getUser().isBot()) // ignore bots vortex.getBasicLogger().logVoiceLeave(gevent); } + else if (event instanceof TextChannelUpdateSlowmodeEvent) + { + vortex.getDatabase().tempslowmodes.clearSlowmode(((TextChannelUpdateSlowmodeEvent) event).getChannel()); + } else if (event instanceof ReadyEvent) { // Log the shard that has finished loading @@ -217,6 +222,7 @@ +event.getJDA().getGuildCache().size()+"` Users: `"+event.getJDA().getUserCache().size()+"`"); vortex.getThreadpool().scheduleWithFixedDelay(() -> vortex.getDatabase().tempbans.checkUnbans(event.getJDA()), 0, 2, TimeUnit.MINUTES); vortex.getThreadpool().scheduleWithFixedDelay(() -> vortex.getDatabase().tempmutes.checkUnmutes(event.getJDA(), vortex.getDatabase().settings), 0, 45, TimeUnit.SECONDS); + vortex.getThreadpool().scheduleWithFixedDelay(() -> vortex.getDatabase().tempslowmodes.checkSlowmode(event.getJDA()), 0, 45, TimeUnit.SECONDS); } } } diff --git a/src/main/java/com/jagrosh/vortex/Vortex.java b/src/main/java/com/jagrosh/vortex/Vortex.java index fa73dcc..146ac66 100644 --- a/src/main/java/com/jagrosh/vortex/Vortex.java +++ b/src/main/java/com/jagrosh/vortex/Vortex.java @@ -128,6 +128,7 @@ new PardonCmd(this), new CheckCmd(this), new ReasonCmd(this), + new SlowmodeCmd(this), // Settings new SetupCmd(this), diff --git a/src/main/java/com/jagrosh/vortex/commands/moderation/BanCmd.java b/src/main/java/com/jagrosh/vortex/commands/moderation/BanCmd.java index 9b052d3..dd4bc73 100644 --- a/src/main/java/com/jagrosh/vortex/commands/moderation/BanCmd.java +++ b/src/main/java/com/jagrosh/vortex/commands/moderation/BanCmd.java @@ -58,9 +58,9 @@ return; } int minutes; - if(args.time < 0) + if(args.time < -1) throw new CommandErrorException("Timed bans cannot be negative time!"); - else if(args.time == 0) + else if(args.time == -1) minutes = 0; else if(args.time > 60) minutes = (int)Math.round(args.time/60.0); diff --git a/src/main/java/com/jagrosh/vortex/commands/moderation/MuteCmd.java b/src/main/java/com/jagrosh/vortex/commands/moderation/MuteCmd.java index 401679c..f7e5def 100644 --- a/src/main/java/com/jagrosh/vortex/commands/moderation/MuteCmd.java +++ b/src/main/java/com/jagrosh/vortex/commands/moderation/MuteCmd.java @@ -72,9 +72,9 @@ return; } int minutes; - if(args.time < 0) + if(args.time < -1) throw new CommandErrorException("Timed mutes cannot be negative time!"); - else if(args.time == 0) + else if(args.time == -1) minutes = 0; else if(args.time > 60) minutes = (int)Math.round(args.time/60.0); diff --git a/src/main/java/com/jagrosh/vortex/commands/moderation/SlowmodeCmd.java b/src/main/java/com/jagrosh/vortex/commands/moderation/SlowmodeCmd.java new file mode 100644 index 0000000..1ed1b69 --- /dev/null +++ b/src/main/java/com/jagrosh/vortex/commands/moderation/SlowmodeCmd.java @@ -0,0 +1,128 @@ +/* + * Copyright 2016 John Grosh (jagrosh). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jagrosh.vortex.commands.moderation; + +import com.jagrosh.jdautilities.command.CommandEvent; +import com.jagrosh.vortex.Vortex; +import com.jagrosh.vortex.commands.ModCommand; +import com.jagrosh.vortex.utils.FormatUtil; +import com.jagrosh.vortex.utils.LogUtil; +import com.jagrosh.vortex.utils.OtherUtil; +import net.dv8tion.jda.api.Permission; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.TimeUnit; + +/** + * @author Michaili K (mysteriouscursor+git@protonmail.com) + */ +public class SlowmodeCmd extends ModCommand +{ + private final static int MAX_SLOWMODE = 21600; + + public SlowmodeCmd(Vortex vortex) + { + super(vortex, Permission.MANAGE_CHANNEL); + this.name = "slowmode"; + this.arguments = "[time or OFF] | [time to disable slowmode]"; + this.help = "enables or disables slowmode"; + this.botPermissions = new Permission[]{Permission.MANAGE_CHANNEL}; + } + + @Override + protected void execute(CommandEvent event) + { + + if(event.getArgs().isEmpty()) + { + int slowmodeDuration = vortex.getDatabase().tempslowmodes.timeUntilDisableSlowmode(event.getTextChannel()); + int slowmodeTime = event.getTextChannel().getSlowmode(); + + if(slowmodeTime <= 0) + { + event.reply("Slowmode is disabled."); + return; + } + + if(slowmodeDuration <= 0) + event.reply("Slowmode is enabled with 1 message every "+FormatUtil.secondsToTimeCompact(slowmodeTime)+"."); + else + event.reply("Slowmode is enabled with 1 message every "+FormatUtil.secondsToTimeCompact(slowmodeTime) + + " for "+FormatUtil.secondsToTimeCompact(slowmodeDuration)+"."); + return; + } + + String args = event.getArgs(); + + if(args.equals("0") || args.equalsIgnoreCase("off")) + { + vortex.getDatabase().tempslowmodes.clearSlowmode(event.getTextChannel()); + event.getTextChannel().getManager() + .setSlowmode(0) + .reason(LogUtil.auditReasonFormat(event.getMember(), "Disabled slowmode")) + .queue(); + event.replySuccess("Disabled slowmode!"); + return; + } + + String[] split = args.split("\\|",2); + + int slowmodeTime = OtherUtil.parseTime(split[0]); + if(slowmodeTime == -1) + { + event.replyError("Invalid slowmode time!"); + return; + } + if(slowmodeTime > MAX_SLOWMODE) + { + event.replyError("You can only enable slowmode for up to 6 hours!"); + return; + } + if(slowmodeTime < -1) + { + event.replyError("Slowmode cannot use negative time!"); + return; + } + + int slowmodeDuration = split.length == 1 ? 0 : OtherUtil.parseTime(split[1]); + if(slowmodeDuration == -1) + { + event.replyError("Invalid slowmode duration time!"); + return; + } + if(slowmodeDuration < -1) + { + event.replyError("Slowmode duration cannot use negative time!"); + return; + } + + event.getTextChannel().getManager() + .setSlowmode(slowmodeTime) + .reason(LogUtil.auditReasonFormat(event.getMember(), slowmodeDuration/60, "Enabled slowmode")) + .queue(s -> + { + if(slowmodeDuration <= 0) return; + vortex.getThreadpool().schedule( + () -> vortex.getDatabase().tempslowmodes.setSlowmode(event.getTextChannel(), Instant.now().plus(slowmodeDuration, ChronoUnit.SECONDS)), + 10, TimeUnit.SECONDS + ); + }); + + event.replySuccess("Enabled slowmode with 1 message every " + FormatUtil.secondsToTimeCompact(slowmodeTime) + + (slowmodeDuration > 0 ? " for "+FormatUtil.secondsToTimeCompact(slowmodeDuration) : "")+"."); + } +} diff --git a/src/main/java/com/jagrosh/vortex/commands/owner/PremiumCmd.java b/src/main/java/com/jagrosh/vortex/commands/owner/PremiumCmd.java index 365cf26..ccdc4ba 100644 --- a/src/main/java/com/jagrosh/vortex/commands/owner/PremiumCmd.java +++ b/src/main/java/com/jagrosh/vortex/commands/owner/PremiumCmd.java @@ -53,7 +53,7 @@ return; } int seconds = OtherUtil.parseTime(parts[1]); - if(seconds == 0) + if(seconds <= 0) { event.replyError("Invalid time"); return; diff --git a/src/main/java/com/jagrosh/vortex/commands/settings/PunishmentCmd.java b/src/main/java/com/jagrosh/vortex/commands/settings/PunishmentCmd.java index 0554479..0c8d675 100644 --- a/src/main/java/com/jagrosh/vortex/commands/settings/PunishmentCmd.java +++ b/src/main/java/com/jagrosh/vortex/commands/settings/PunishmentCmd.java @@ -92,7 +92,18 @@ case "temp-mute": case "mute": { - int minutes = parts.length>2 ? OtherUtil.parseTime(parts[2])/60 : 0; + int minutes = 0; + if(parts.length > 2) + { + int parseResult = OtherUtil.parseTime(parts[2]); + if(parseResult == -1) + { + event.replyError("Invalid time!"); + return; + } + minutes = parseResult/60; + } + if(minutes<0) { event.replyError("Temp-Mute time cannot be negative!"); @@ -120,7 +131,18 @@ case "temp-ban": case "ban": { - int minutes = parts.length>2 ? OtherUtil.parseTime(parts[2])/60 : 0; + int minutes = 0; + if(parts.length > 2) + { + int parseResult = OtherUtil.parseTime(parts[2]); + if(parseResult == -1) + { + event.replyError("Invalid time!"); + return; + } + minutes = parseResult/60; + } + if(minutes<0) { event.replyError("Temp-Ban time cannot be negative!"); diff --git a/src/main/java/com/jagrosh/vortex/commands/tools/ExportCmd.java b/src/main/java/com/jagrosh/vortex/commands/tools/ExportCmd.java index 979be27..1056fbe 100644 --- a/src/main/java/com/jagrosh/vortex/commands/tools/ExportCmd.java +++ b/src/main/java/com/jagrosh/vortex/commands/tools/ExportCmd.java @@ -57,6 +57,7 @@ .put("punishments", db.actions.getAllPunishmentsJson(g)) .put("tempmutes", db.tempmutes.getAllMutesJson(g)) .put("tempbans", db.tempbans.getAllBansJson(g)) + .put("tempslowmodes", db.tempslowmodes.getAllSlowmodesJson(g)) .put("inviteWhitelist", db.inviteWhitelist.getWhitelistJson(g)) .put("filters", db.filters.getFiltersJson(g)) .put("premium", db.premium.getPremiumInfoJson(g)); diff --git a/src/main/java/com/jagrosh/vortex/database/Database.java b/src/main/java/com/jagrosh/vortex/database/Database.java index 6913636..4f638bd 100644 --- a/src/main/java/com/jagrosh/vortex/database/Database.java +++ b/src/main/java/com/jagrosh/vortex/database/Database.java @@ -32,6 +32,7 @@ public final PunishmentManager actions; // strike punishment settings public final TempMuteManager tempmutes; public final TempBanManager tempbans; + public final TempSlowmodeManager tempslowmodes; public final PremiumManager premium; public final InviteWhitelistManager inviteWhitelist; public final FilterManager filters; @@ -48,6 +49,7 @@ actions = new PunishmentManager(this); tempmutes = new TempMuteManager(this); tempbans = new TempBanManager(this); + tempslowmodes = new TempSlowmodeManager(this); premium = new PremiumManager(this); inviteWhitelist = new InviteWhitelistManager(this); filters = new FilterManager(this); diff --git a/src/main/java/com/jagrosh/vortex/database/managers/TempSlowmodeManager.java b/src/main/java/com/jagrosh/vortex/database/managers/TempSlowmodeManager.java new file mode 100644 index 0000000..51214f9 --- /dev/null +++ b/src/main/java/com/jagrosh/vortex/database/managers/TempSlowmodeManager.java @@ -0,0 +1,125 @@ +/* + * Copyright 2018 John Grosh (john.a.grosh@gmail.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jagrosh.vortex.database.managers; + +import com.jagrosh.easysql.DataManager; +import com.jagrosh.easysql.DatabaseConnector; +import com.jagrosh.easysql.SQLColumn; +import com.jagrosh.easysql.columns.InstantColumn; +import com.jagrosh.easysql.columns.LongColumn; +import com.jagrosh.vortex.utils.Pair; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.TextChannel; +import org.json.JSONObject; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Michail K (mysteriouscursor+git@protonmail.com) + */ +public class TempSlowmodeManager extends DataManager +{ + public static final SQLColumn CHANNEL_ID = new LongColumn("CHANNEL_ID", false, 0, true); + public static final SQLColumn FINISH = new InstantColumn("FINISH", false, Instant.EPOCH); + + public TempSlowmodeManager(DatabaseConnector connector) + { + super(connector, "TEMP_SLOWMODES"); + } + + public JSONObject getAllSlowmodesJson(Guild guild) + { + List> list = new ArrayList<>(); + for(TextChannel channel : guild.getTextChannels()) + { + read(selectAll(CHANNEL_ID.is(channel.getId())), rs -> + { + if(rs.next()) + list.add(new Pair<>(CHANNEL_ID.getValue(rs), FINISH.getValue(rs))); + }); + } + + JSONObject json = new JSONObject(); + list.forEach(p -> json.put(Long.toString(p.getKey()), p.getValue().getEpochSecond())); + return json; + } + + public void setSlowmode(TextChannel channel, Instant finish) + { + readWrite(selectAll(CHANNEL_ID.is(channel.getId())), rs -> + { + if(rs.next()) + { + FINISH.updateValue(rs, finish); + rs.updateRow(); + } + else + { + rs.moveToInsertRow(); + CHANNEL_ID.updateValue(rs, channel.getIdLong()); + FINISH.updateValue(rs, finish); + rs.insertRow(); + } + }); + } + + public void clearSlowmode(TextChannel channel) + { + readWrite(selectAll(CHANNEL_ID.is(channel.getId())), rs -> + { + if(rs.next()) + rs.deleteRow(); + }); + } + + public int timeUntilDisableSlowmode(TextChannel channel) + { + return read(selectAll(CHANNEL_ID.is(channel.getId())), rs -> + { + if(rs.next()) + { + Instant end = FINISH.getValue(rs); + if(end==Instant.MAX) + return 0; + else + return (int)(Instant.now().until(end, ChronoUnit.SECONDS)); + } + return 0; + }); + } + + public void checkSlowmode(JDA jda) + { + readWrite(selectAll(FINISH.isLessThan(Instant.now().getEpochSecond())), rs -> + { + while(rs.next()) + { + TextChannel tc = jda.getTextChannelById(CHANNEL_ID.getValue(rs)); + if(tc==null) + continue; + if(tc.getGuild().getSelfMember().hasPermission(tc, Permission.MANAGE_CHANNEL)) + tc.getManager().setSlowmode(0).reason("Temporary Slowmode Completed").queue(s->{}, f->{}); + rs.deleteRow(); + } + }); + } +} diff --git a/src/main/java/com/jagrosh/vortex/utils/ArgsUtil.java b/src/main/java/com/jagrosh/vortex/utils/ArgsUtil.java index 242a19e..7bdeed3 100644 --- a/src/main/java/com/jagrosh/vortex/utils/ArgsUtil.java +++ b/src/main/java/com/jagrosh/vortex/utils/ArgsUtil.java @@ -112,7 +112,7 @@ found = true; } } - int time = 0; + int time = -1; if(allowTime) { String timeString = args.replaceAll(TIME_REGEX, "$1"); diff --git a/src/main/java/com/jagrosh/vortex/utils/OtherUtil.java b/src/main/java/com/jagrosh/vortex/utils/OtherUtil.java index a0b6721..0556bbf 100644 --- a/src/main/java/com/jagrosh/vortex/utils/OtherUtil.java +++ b/src/main/java/com/jagrosh/vortex/utils/OtherUtil.java @@ -91,18 +91,23 @@ for(int j=0; j j+1) + { + if(vals[j+1].toLowerCase().startsWith("m")) + num*=60; + else if(vals[j+1].toLowerCase().startsWith("h")) + num*=60*60; + else if(vals[j+1].toLowerCase().startsWith("d")) + num*=60*60*24; + } + timeinseconds+=num; } } catch(Exception ex) { - return 0; + return -1; } return timeinseconds; }