diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 901ba2f..707410b 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.fpghoti Biscuit - 1.4 + 1.5 src/main/java diff --git a/pom.xml b/pom.xml index 844db07..88960f7 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.fpghoti Biscuit - 1.4 + 1.5 src/main/java diff --git a/src/main/java/com/fpghoti/biscuit/Biscuit.java b/src/main/java/com/fpghoti/biscuit/Biscuit.java index d04410d..de15b66 100644 --- a/src/main/java/com/fpghoti/biscuit/Biscuit.java +++ b/src/main/java/com/fpghoti/biscuit/Biscuit.java @@ -2,6 +2,7 @@ package com.fpghoti.biscuit; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Timer; @@ -15,7 +16,9 @@ import com.fpghoti.biscuit.user.PreUser; import com.github.cage.Cage; 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.Invite; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.TextChannel; @@ -30,7 +33,7 @@ public class Biscuit { private List timers; private File captchaDir; private Cage cage; - + private HashMap inviteUses; public Biscuit(JDA jda, Logger log) { this.jda = jda; @@ -48,6 +51,23 @@ public class Biscuit { cage = new BCage(); wipeCaptchaDir(); loadPreUsers(); + inviteUses = new HashMap(); + if(canManageServer() && PropertiesRetrieval.checkJoinInvite()) { + for(Guild g : jda.getGuilds()) { + g.retrieveInvites().queue((invs) -> { + indexInvites(invs); + }); + } + } + } + + public boolean canManageServer() { + for(Guild g : jda.getGuilds()) { + if(g.getSelfMember().hasPermission(Permission.MANAGE_SERVER)) { + return true; + } + } + return false; } public void log(String message) { @@ -74,7 +94,6 @@ public class Biscuit { channel.sendMessage(message).queue(); } - public void loadTimers() { timer.cancel(); timer = new Timer(); @@ -111,6 +130,26 @@ public class Biscuit { public Cage getCage() { return this.cage; } + + public ArrayList getCaptchaLogChannels() { + ArrayList ch = new ArrayList(); + for(Guild g : jda.getGuilds()) { + for(TextChannel t : g.getTextChannels()) { + if(t.getName().equalsIgnoreCase(PropertiesRetrieval.getCaptchaLogChannel())) { + ch.add(t); + } + } + } + return ch; + } + + public void captchaLog(String msg) { + if(PropertiesRetrieval.logCaptcha()) { + for(TextChannel t : getCaptchaLogChannels()) { + t.sendMessage(msg).queue(); + } + } + } private void loadPreUsers() { for(Guild g : jda.getGuilds()) { @@ -130,5 +169,24 @@ public class Biscuit { } + private void indexInvites(List invs) { + for(Invite i : invs) { + String code = i.getCode(); + int uses = i.getUses(); + inviteUses.put(code, uses); + } + } + + public HashMap getInviteUses(){ + return inviteUses; + } + + public void setInviteUses(HashMap c) { + inviteUses = c; + } + + public void clearInviteUses() { + inviteUses.clear(); + } } diff --git a/src/main/java/com/fpghoti/biscuit/Main.java b/src/main/java/com/fpghoti/biscuit/Main.java index 5894278..74a87fb 100644 --- a/src/main/java/com/fpghoti/biscuit/Main.java +++ b/src/main/java/com/fpghoti/biscuit/Main.java @@ -15,6 +15,7 @@ import com.fpghoti.biscuit.commands.client.ToggleRoleCommand; import com.fpghoti.biscuit.commands.client.HelpCommand; import com.fpghoti.biscuit.commands.client.MultiplyCommand; import com.fpghoti.biscuit.commands.client.NotSpammerCommand; +import com.fpghoti.biscuit.commands.client.MakeInviteCommand; import com.fpghoti.biscuit.commands.client.PingCommand; import com.fpghoti.biscuit.commands.client.PowerCommand; import com.fpghoti.biscuit.commands.client.RecentSpammersCommand; @@ -107,6 +108,7 @@ public class Main { commands.add(new MultiplyCommand()); commands.add(new DivideCommand()); commands.add(new PowerCommand()); + commands.add(new MakeInviteCommand()); //Console diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java new file mode 100644 index 0000000..f9a168e --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java @@ -0,0 +1,60 @@ +package com.fpghoti.biscuit.commands.client; + +import com.fpghoti.biscuit.Biscuit; +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.config.PropertiesRetrieval; +import com.fpghoti.biscuit.util.PermUtil; +import com.fpghoti.biscuit.util.Util; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class MakeInviteCommand extends ClientCommand{ + + public MakeInviteCommand() { + name = "Make Invite"; + description = "Creates an invite in the specified channel"; + usage = PropertiesRetrieval.getCommandSignifier() + "makeinvite [max-age-hours]"; + minArgs = 1; + maxArgs = 2; + identifiers.add("makeinvite"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + double doubAge = 0; + if(args.length == 2 && Util.isDeciDigit(args[1])) { + doubAge = Double.parseDouble(args[1]) * 3600; + } + int maxAge = (int)Math.round(doubAge); + Biscuit b = Main.getBiscuit(); + b.log(event.getAuthor().getName() + " issued a command: -makeinvite " + args[0]); + if((PermUtil.isAdmin(event.getMember()))) { + for(Guild g : b.getJDA().getGuilds()) { + TextChannel c = null; + for(TextChannel t : g.getTextChannels()) { + if(t.getName().equalsIgnoreCase(args[0])) { + c = t; + } + } + if(doubAge > 86400) { + event.getChannel().sendMessage("That length is longer than what Discord allows. Please try again. (Max 24 hours)").queue(); + return; + } + final double db = doubAge; + if(c != null) { + c.createInvite().setMaxAge(maxAge).queue((i) -> { + String exp = "Never"; + if(db > 0) { + exp = args[1] + " hour(s)"; + } + event.getChannel().sendMessage("Created invite **" + i.getCode() + "** Expiration: **" + exp + "**.").queue(); + }); + } + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/config/ConfigRetrieval.java b/src/main/java/com/fpghoti/biscuit/config/ConfigRetrieval.java index d49c6c8..21e0955 100644 --- a/src/main/java/com/fpghoti/biscuit/config/ConfigRetrieval.java +++ b/src/main/java/com/fpghoti/biscuit/config/ConfigRetrieval.java @@ -95,6 +95,9 @@ public class ConfigRetrieval { added = addProperty("Toggle-Role-React-Channels", "toggleroles1,toggleroles2,toggleroles3", prop, added); added = addProperty("Boost-Exclusive-Roles", "role2,role3", prop, added); added = addProperty("Treat-Like-Booster", "Nitro Booster,silver,gold", prop, added); + added = addProperty("LogCaptcha", "false", prop, added); + added = addProperty("Captcha-Log-Channel", "verify-log", prop, added); + added = addProperty("Check-Join-Invite", "false", prop, added); return added; } diff --git a/src/main/java/com/fpghoti/biscuit/config/PropertiesRetrieval.java b/src/main/java/com/fpghoti/biscuit/config/PropertiesRetrieval.java index e59f438..519edb4 100644 --- a/src/main/java/com/fpghoti/biscuit/config/PropertiesRetrieval.java +++ b/src/main/java/com/fpghoti/biscuit/config/PropertiesRetrieval.java @@ -46,6 +46,20 @@ public class PropertiesRetrieval { return ConfigRetrieval.getFromConfig("AdminRole"); } + public static String getCaptchaLogChannel(){ + return ConfigRetrieval.getFromConfig("Captcha-Log-Channel"); + } + + public static boolean logCaptcha(){ + String value = ConfigRetrieval.getFromConfig("LogCaptcha"); + return value.equalsIgnoreCase("true"); + } + + public static boolean checkJoinInvite(){ + String value = ConfigRetrieval.getFromConfig("Check-Join-Invite"); + return value.equalsIgnoreCase("true"); + } + public static boolean noCaptchaKick(){ String value = ConfigRetrieval.getFromConfig("No-Captcha-Kick"); return value.equalsIgnoreCase("true"); diff --git a/src/main/java/com/fpghoti/biscuit/listener/DMListener.java b/src/main/java/com/fpghoti/biscuit/listener/DMListener.java index 07d5d8e..3c32992 100644 --- a/src/main/java/com/fpghoti/biscuit/listener/DMListener.java +++ b/src/main/java/com/fpghoti/biscuit/listener/DMListener.java @@ -139,6 +139,7 @@ public class DMListener extends ListenerAdapter{ } preu.setDone(); Main.log.info(tlabel + author.getName() + " successfully completed a captcha challenge. Granting role."); + Main.getBiscuit().captchaLog("" + tlabel + " ``" + author.getName() +"`` " + author.getAsMention() + " successfully completed a captcha challenge. Granting role."); Role newrole = null; Role defaultrole = null; diff --git a/src/main/java/com/fpghoti/biscuit/listener/JoinListener.java b/src/main/java/com/fpghoti/biscuit/listener/JoinListener.java index 2c84651..d388e9c 100644 --- a/src/main/java/com/fpghoti/biscuit/listener/JoinListener.java +++ b/src/main/java/com/fpghoti/biscuit/listener/JoinListener.java @@ -1,11 +1,17 @@ package com.fpghoti.biscuit.listener; +import java.util.HashMap; + import org.slf4j.Logger; +import com.fpghoti.biscuit.Biscuit; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.config.PropertiesRetrieval; import com.fpghoti.biscuit.user.PreUser; +import com.jcabi.aspects.Async; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Invite; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; @@ -17,8 +23,15 @@ public class JoinListener extends ListenerAdapter { @Override public void onGuildMemberJoin(GuildMemberJoinEvent event) { + Biscuit b = Main.getBiscuit(); User user = event.getMember().getUser(); - log.info("MEMBER JOINED: " + user.getName() + " " + user.getAsMention()); + log.info("USER JOINED: " + user.getName() + " " + user.getAsMention()); + b.captchaLog("**User Joined:** ``" + user.getName() + "`` " + user.getAsMention()); + if(b.canManageServer() && PropertiesRetrieval.checkJoinInvite()) { + logUserInvite(user); + }else { + b.clearInviteUses(); + } if(PropertiesRetrieval.customDefaultRole()) { if(!event.getMember().getUser().isBot()) { log.info("Issuing a role.."); @@ -42,6 +55,33 @@ public class JoinListener extends ListenerAdapter { } } } + + @Async + private void logUserInvite(final User user){ + final Biscuit b = Main.getBiscuit(); + for(Guild g : b.getJDA().getGuilds()) { + g.retrieveInvites().queue((invs) -> { + String usedInv = "Other"; + HashMap newinv = new HashMap(); + boolean empty = b.getInviteUses().isEmpty(); + for(Invite i : invs) { + String code = i.getCode(); + int uses = i.getUses(); + newinv.put(code, uses); + if(!empty &&(!b.getInviteUses().containsKey(code) || b.getInviteUses().get(code) != uses)) { + usedInv = code; + } + } + if(empty) { + log.info("The ability for the bot to check the invites has only recently been enabled, so there is not enough data to determine the invite used. This should be fixed by the next time a user joins the server."); + usedInv = "Unknown"; + } + b.setInviteUses(newinv); + log.info("INVITE INFO: " + user.getName() + " used invite: " + usedInv); + b.captchaLog("**Invite Info:** ``" + user.getName() + "`` used invite: ``" + usedInv + "``"); + }); + } + } } \ No newline at end of file diff --git a/src/main/java/com/fpghoti/biscuit/user/PreUser.java b/src/main/java/com/fpghoti/biscuit/user/PreUser.java index b58def2..e728a68 100644 --- a/src/main/java/com/fpghoti/biscuit/user/PreUser.java +++ b/src/main/java/com/fpghoti/biscuit/user/PreUser.java @@ -93,7 +93,8 @@ public class PreUser { timeLeft = timeLeft - 1; if(timeLeft <= 0) { for(Guild g : getGuilds()) { - Main.log.info(user.getName() + " " + user.getAsMention() + " waited too long to complete the captcha! Kicking..."); + Main.log.info(user.getName() + " " + user.getAsMention() + " waited too long to complete the captcha. Kicking..."); + Main.getBiscuit().captchaLog("``" + user.getName() +"`` " + user.getAsMention() + " waited too long to complete the captcha! Kicking..."); g.kick(user.getId()).queue(); remove(); } diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index cca4132..1ba1206 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -78,6 +78,16 @@ DisabledCommands = cmd1,cmd2,cmd3 #Disabled these commands for normal users DisabledUserCommands = cmd4,cmd5,cmd6 +#Checks which invite users join with. Requires bot to have Manage Server permission. +Check-Join-Invite = false + +#Enables the captcha text-channel logging. +#Logs join, complete captcha, invite joined with, and time-out kick +LogCaptcha = false + +#Put the name of the text channel you want to log captcha information to. +Captcha-Log-Channel = verify-log + #List your custom commands here. This line will always generate blank. #Example - Custom-Command-Names = hello,botcheck,apple Custom-Command-Names =