diff --git a/src/main/java/io/github/jdiscordbots/mee/bypasser/MsgListener.java b/src/main/java/io/github/jdiscordbots/mee/bypasser/MsgListener.java index 4274555..4654a7f 100644 --- a/src/main/java/io/github/jdiscordbots/mee/bypasser/MsgListener.java +++ b/src/main/java/io/github/jdiscordbots/mee/bypasser/MsgListener.java @@ -1,201 +1,205 @@ -package io.github.jdiscordbots.mee.bypasser; - -import io.github.jdiscordbots.mee.bypasser.model.db.GuildInformation; -import io.github.jdiscordbots.mee.bypasser.ocr.MeeImageRecognition; -import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed.AuthorInfo; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.events.ShutdownEvent; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.sourceforge.tess4j.TesseractException; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class MsgListener extends ListenerAdapter { - - private static final long RATE_LIMIT = 1000L; - private static final Logger LOG = LoggerFactory.getLogger(MsgListener.class); - private static final Pattern rankPattern = Pattern.compile("!rank (?:(?\\d+)|[<][@][!]?(?\\d+)[>])"); - - private DataBaseController database; - private ExecutorService imageProcessingPool=Executors.newSingleThreadExecutor(); - - public MsgListener() { - database = DataBaseController.getInstance(); - } - - private static boolean hasModPerm(Member member) { - return member.hasPermission(Permission.MANAGE_ROLES); - } - - public static class Holder { - private T val; - - - public Holder(T val) { - this.val = val; - } - - public T get() { - return val; - } - - public void set(T val) { - this.val = val; - } - - } - - @Override - public void onMessageReceived(@NotNull MessageReceivedEvent event) { - if(!event.isFromGuild()) { - return; - } - if(event.getMember() == null) { - return; - } - if(!event.getMember().getUser().isBot() - || event.getAuthor().getIdLong() != 159985870458322944L) { //check if message is from Mee6 - return; - } - if(event.getGuild().getSelfMember().hasPermission(event.getGuildChannel(), Permission.MESSAGE_HISTORY)) { - Message.Interaction interaction = event.getMessage().getInteraction(); - if(interaction == null) { - event.getGuildChannel().getHistory().retrievePast(2).queue(messages -> { - if(messages.size() == 2) { - Message message = messages.get(1); - Matcher rankPatternMatcher = rankPattern.matcher(message.getContentRaw()); - if("!rank".equals(message.getContentRaw())) { - if(message.getMember() == null) { - event.getGuild().retrieveMemberById(message.getAuthor().getId()).queue(actualMember -> { - updateRole(actualMember, event, actualMember); - }); - } else { - updateRole(message.getMember(), event, message.getMember()); - } - } else if(rankPatternMatcher.matches()) { - String id = rankPatternMatcher.group("id1"); - if(id == null) { - id = rankPatternMatcher.group("id2"); - } - event.getGuild().retrieveMemberById(id).queue(member -> updateRole(member, event, message.getMember()), memberNotFound->{/*ignore*/}); - } - } - }); - } else { - if("rank".equals(interaction.getName())) { - Member member = interaction.getMember(); - if(member != null) { - event.getChannel().retrieveMessageById(event.getMessageId()).queueAfter(1, TimeUnit.SECONDS, - msg -> updateRole(member, event, msg, member)); - } - } - - } - } - } - - private void runIfMemberByPrefixFound(Guild g, AuthorInfo author, Consumer toRun) { - g.retrieveMembersByPrefix(author.getName(), 1).onSuccess(members -> { - if(!members.isEmpty()) { - toRun.accept(members.get(0)); - } - }); - } - - private void updateRole(Member member, MessageReceivedEvent event, Member author) { - updateRole(member, event, event.getMessage(), author); - } - - private void updateRole(Member member, MessageReceivedEvent event, Message msg, Member author) { - final List attachments = msg.getAttachments(); - if(attachments.size() != 1) { - return; - } - final Message.Attachment attachment = attachments.get(0); - if(attachment.getContentType() == null || !attachment.getContentType().startsWith("image/")) { - return; - } - final GuildInformation guildInfo = database.loadGuildInformation(event.getGuild().getId()); - if(guildInfo.getLastRankCall() + RATE_LIMIT > System.currentTimeMillis()) { - return; - } - guildInfo.setLastRankCall(System.currentTimeMillis()); - database.save(guildInfo); - attachment.retrieveInputStream().thenAcceptAsync(is -> { - try { - MeeImageRecognition.LevelInfo levelInfo = MeeImageRecognition.loadDataFromImage(is); - if(String.valueOf(levelInfo.getDiscrimminator()).equals(member.getUser().getDiscriminator())) { - guildInfo.getRoleIdsAtLevel(levelInfo.getLevel()).forEach((roleId, add) -> { - final Role role = member.getGuild().getRoleById(roleId); - if(role != null) { - if(hasModPerm(member.getGuild().getSelfMember()) - && member.getGuild().getSelfMember().canInteract(role)) { - if(add) { - if(!member.getRoles().contains(role)) { - member.getGuild().addRoleToMember(member, role).queue(); - } - } else { - if(member.getRoles().contains(role)) { - member.getGuild().removeRoleFromMember(member, role).queue(); - } - } - } else if(author.hasPermission(Permission.ADMINISTRATOR)) { - event.getChannel().sendMessage("Cannot assign role " + role.getName() + " as " - + member.getGuild().getSelfMember().getEffectiveName() - + " does not have the necessary permissions.").queue(); - } - } - }); - } - } catch(IOException e) { - LOG.atError() - .addArgument(event::getGuild) - .setCause(e) - .log("An I/O error occurred trying to read the image in guild {}."); - } catch(TesseractException e) { - LOG.atInfo() - .addArgument(event::getGuild) - .setCause(e) - .log("An error occurred trying to parse the image in guild {}."); - } catch(UnsatisfiedLinkError e) { - LOG.atError() - .addArgument(event::getGuild) - .setCause(e) - .log("An error occured trying to load libraries during parsing the image in guild {}."); - } - },imageProcessingPool) - .exceptionally(e -> { - LOG.atError() - .addArgument(event::getGuild) - .setCause(e) - .log("An unknown error occurred trying to load levels in guild {}."); - return null; - }); - - } - - @Override - public void onShutdown(ShutdownEvent event) { - try { - database.close(); - } catch(Exception e) { - LOG.error("cannot close database", e); - } - } - -} +package io.github.jdiscordbots.mee.bypasser; + +import io.github.jdiscordbots.mee.bypasser.model.db.GuildInformation; +import io.github.jdiscordbots.mee.bypasser.ocr.MeeImageRecognition; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed.AuthorInfo; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.events.ShutdownEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.sourceforge.tess4j.TesseractException; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MsgListener extends ListenerAdapter { + + private static final long RATE_LIMIT = 1000L; + private static final Logger LOG = LoggerFactory.getLogger(MsgListener.class); + private static final Pattern rankPattern = Pattern.compile("!rank (?:(?\\d+)|[<][@][!]?(?\\d+)[>])"); + + private DataBaseController database; + private ExecutorService imageProcessingPool=Executors.newSingleThreadExecutor(); + + public MsgListener() { + database = DataBaseController.getInstance(); + } + + private static boolean hasModPerm(Member member) { + return member.hasPermission(Permission.MANAGE_ROLES); + } + + public static class Holder { + private T val; + + + public Holder(T val) { + this.val = val; + } + + public T get() { + return val; + } + + public void set(T val) { + this.val = val; + } + + } + + @Override + public void onMessageReceived(@NotNull MessageReceivedEvent event) { + if(!event.isFromGuild()) { + return; + } + if(event.getMember() == null) { + return; + } + if(!event.getMember().getUser().isBot() + || event.getAuthor().getIdLong() != 159985870458322944L) { //check if message is from Mee6 + return; + } + if(event.getGuild().getSelfMember().hasPermission(event.getGuildChannel(), Permission.MESSAGE_HISTORY)) { + Message.Interaction interaction = event.getMessage().getInteraction(); + if(interaction == null) { + event.getGuildChannel().getHistory().retrievePast(2).queue(messages -> { + System.out.println(messages.size() + "msg size"); + if(messages.size() == 2) { + Message message = messages.get(1); + Matcher rankPatternMatcher = rankPattern.matcher(message.getContentRaw()); + System.out.println(message.getContentRaw() + "raw msg"); + if("!rank".equals(message.getContentRaw())) { + if(message.getMember() == null) { + System.out.println("getMember() = null"); + event.getGuild().retrieveMemberById(message.getAuthor().getId()).queue(actualMember -> { + updateRole(actualMember, event, actualMember); + }); + } else { + System.out.println("message.getMember()"); + updateRole(message.getMember(), event, message.getMember()); + } + } else if(rankPatternMatcher.matches()) { + String id = rankPatternMatcher.group("id1"); + if(id == null) { + id = rankPatternMatcher.group("id2"); + } + event.getGuild().retrieveMemberById(id).queue(member -> updateRole(member, event, message.getMember()), memberNotFound->{/*ignore*/}); + } + } + }); + } else { + if("rank".equals(interaction.getName())) { + Member member = interaction.getMember(); + if(member != null) { + event.getChannel().retrieveMessageById(event.getMessageId()).queueAfter(1, TimeUnit.SECONDS, + msg -> updateRole(member, event, msg, member)); + } + } + + } + } + } + + private void runIfMemberByPrefixFound(Guild g, AuthorInfo author, Consumer toRun) { + g.retrieveMembersByPrefix(author.getName(), 1).onSuccess(members -> { + if(!members.isEmpty()) { + toRun.accept(members.get(0)); + } + }); + } + + private void updateRole(Member member, MessageReceivedEvent event, Member author) { + updateRole(member, event, event.getMessage(), author); + } + + private void updateRole(Member member, MessageReceivedEvent event, Message msg, Member author) { + final List attachments = msg.getAttachments(); + if(attachments.size() != 1) { + return; + } + final Message.Attachment attachment = attachments.get(0); + if(attachment.getContentType() == null || !attachment.getContentType().startsWith("image/")) { + return; + } + final GuildInformation guildInfo = database.loadGuildInformation(event.getGuild().getId()); + if(guildInfo.getLastRankCall() + RATE_LIMIT > System.currentTimeMillis()) { + return; + } + guildInfo.setLastRankCall(System.currentTimeMillis()); + database.save(guildInfo); + attachment.retrieveInputStream().thenAcceptAsync(is -> { + try { + MeeImageRecognition.LevelInfo levelInfo = MeeImageRecognition.loadDataFromImage(is); + if(String.valueOf(levelInfo.getDiscrimminator()).equals(member.getUser().getDiscriminator())) { + guildInfo.getRoleIdsAtLevel(levelInfo.getLevel()).forEach((roleId, add) -> { + final Role role = member.getGuild().getRoleById(roleId); + if(role != null) { + if(hasModPerm(member.getGuild().getSelfMember()) + && member.getGuild().getSelfMember().canInteract(role)) { + if(add) { + if(!member.getRoles().contains(role)) { + member.getGuild().addRoleToMember(member, role).queue(); + } + } else { + if(member.getRoles().contains(role)) { + member.getGuild().removeRoleFromMember(member, role).queue(); + } + } + } else if(author.hasPermission(Permission.ADMINISTRATOR)) { + event.getChannel().sendMessage("Cannot assign role " + role.getName() + " as " + + member.getGuild().getSelfMember().getEffectiveName() + + " does not have the necessary permissions.").queue(); + } + } + }); + } + } catch(IOException e) { + LOG.atError() + .addArgument(event::getGuild) + .setCause(e) + .log("An I/O error occurred trying to read the image in guild {}."); + } catch(TesseractException e) { + LOG.atInfo() + .addArgument(event::getGuild) + .setCause(e) + .log("An error occurred trying to parse the image in guild {}."); + } catch(UnsatisfiedLinkError e) { + LOG.atError() + .addArgument(event::getGuild) + .setCause(e) + .log("An error occured trying to load libraries during parsing the image in guild {}."); + } + },imageProcessingPool) + .exceptionally(e -> { + LOG.atError() + .addArgument(event::getGuild) + .setCause(e) + .log("An unknown error occurred trying to load levels in guild {}."); + return null; + }); + + } + + @Override + public void onShutdown(ShutdownEvent event) { + try { + database.close(); + } catch(Exception e) { + LOG.error("cannot close database", e); + } + } + +} diff --git a/src/main/java/io/github/jdiscordbots/mee/bypasser/ocr/MeeImageRecognition.java b/src/main/java/io/github/jdiscordbots/mee/bypasser/ocr/MeeImageRecognition.java index 1d2f8ca..3515b8f 100644 --- a/src/main/java/io/github/jdiscordbots/mee/bypasser/ocr/MeeImageRecognition.java +++ b/src/main/java/io/github/jdiscordbots/mee/bypasser/ocr/MeeImageRecognition.java @@ -1,88 +1,94 @@ -package io.github.jdiscordbots.mee.bypasser.ocr; - -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.net.URL; -import java.nio.file.Files; - -import javax.imageio.ImageIO; - -import net.sourceforge.tess4j.Tesseract; -import net.sourceforge.tess4j.TesseractException; - -public class MeeImageRecognition { - private static final Tesseract tesseract = new Tesseract(); - - static{ - File trainingPath = new File(".tesseract"); - - trainingPath.mkdirs(); - File trainingDataFile = new File(trainingPath, "eng.traineddata"); - if(!trainingDataFile.exists()){ - try(BufferedInputStream bis = new BufferedInputStream(new URL("https://github.com/tesseract-ocr/tessdata/blob/main/eng.traineddata?raw=true").openStream())){ - Files.copy(bis, trainingDataFile.toPath()); - }catch(IOException e){ - throw new UncheckedIOException(e); - } - } - tesseract.setDatapath(trainingPath.getAbsolutePath()); - tesseract.setVariable("tessedit_char_whitelist", "RANK#LEV0123456789"); - tesseract.setVariable("user_defined_dpi", "300"); - - } - - public static LevelInfo loadDataFromImage(InputStream imageInput) throws IOException, TesseractException { - BufferedImage img = ImageIO.read(imageInput); - return new LevelInfo(loadRankTextFromImage(img), loadDiscrimminatorFromImage(img)); - } - - private static int loadDiscrimminatorFromImage(BufferedImage img) throws TesseractException { - String seperator = "#"; - Rectangle rect = new Rectangle(200, 122, img.getWidth() - 200 - 45, 75); - return loadIntFromImage(img, seperator, rect); - } - - private static int loadRankTextFromImage(BufferedImage img) throws TesseractException { - String prelevel = "LEVEL"; - Rectangle rect = new Rectangle(569, 0, img.getWidth() - 569, 118); - return loadIntFromImage(img, prelevel, rect); - } - - private static int loadIntFromImage(BufferedImage img, String seperator, Rectangle rect) throws TesseractException { - String infoText = tesseract.doOCR(img, rect); - int levelIndex = infoText.indexOf(seperator); - if(levelIndex == -1){ - return -1; - }else{ - try{ - int beginIndex = levelIndex + seperator.length(); - return Integer.parseInt(infoText.substring(beginIndex, Math.min(beginIndex + 4, infoText.length())).replace(" ", "").trim()); - }catch(NumberFormatException e){ - return -1; - } - } - } - - public static class LevelInfo { - private final int level; - private final int discrimminator; - - public LevelInfo(int level, int discrimminator) { - this.level = level; - this.discrimminator = discrimminator; - } - - public int getLevel() { - return level; - } - - public int getDiscrimminator() { - return discrimminator; - } - } -} +package io.github.jdiscordbots.mee.bypasser.ocr; + +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.file.Files; + +import javax.imageio.ImageIO; + +import net.sourceforge.tess4j.Tesseract; +import net.sourceforge.tess4j.TesseractException; + +public class MeeImageRecognition { + private static final Tesseract tesseract = new Tesseract(); + + static { + File trainingPath = new File(".tesseract"); + + trainingPath.mkdirs(); + File trainingDataFile = new File(trainingPath, "eng.traineddata"); + if (!trainingDataFile.exists()) { + try (BufferedInputStream bis = new BufferedInputStream( + new URL("https://github.com/tesseract-ocr/tessdata/blob/main/eng.traineddata?raw=true") + .openStream())) { + Files.copy(bis, trainingDataFile.toPath()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + tesseract.setDatapath(trainingPath.getAbsolutePath()); + tesseract.setVariable("tessedit_char_whitelist", "RANK#LEV0123456789"); + tesseract.setVariable("user_defined_dpi", "300"); + + } + + public static LevelInfo loadDataFromImage(InputStream imageInput) throws IOException, TesseractException { + BufferedImage img = ImageIO.read(imageInput); + return new LevelInfo(loadRankTextFromImage(img), loadDiscrimminatorFromImage(img)); + } + + private static int loadDiscrimminatorFromImage(BufferedImage img) throws TesseractException { + String seperator = "#"; + Rectangle rect = new Rectangle(400, 122, img.getWidth() - 200 - 45, 75); + return loadIntFromImage(img, seperator, rect); + } + + private static int loadRankTextFromImage(BufferedImage img) throws TesseractException { + String prelevel = "LEVEL"; + Rectangle rect = new Rectangle(569, 0, img.getWidth() - 569, 118); + return loadIntFromImage(img, prelevel, rect); + } + + private static int loadIntFromImage(BufferedImage img, String seperator, Rectangle rect) throws TesseractException { + String infoText = tesseract.doOCR(img, rect); + int levelIndex = infoText.indexOf(seperator); + System.out.println(infoText + "InfoTxt"); + if (levelIndex == -1) { + return -1; + } else { + try { + int beginIndex = levelIndex + seperator.length(); + return Integer.parseInt(infoText.substring(beginIndex, Math.min(beginIndex + 4, infoText.length())) + .replace(" ", "").trim()); + } catch (NumberFormatException e) { + return -1; + } + } + } + + public static class LevelInfo { + private final int level; + private final int discrimminator; + + public LevelInfo(int level, int discrimminator) { + this.level = level; + this.discrimminator = discrimminator; + System.out.print(this.level + "lvl"); + System.out.println(this.discrimminator + "discrim"); + } + + public int getLevel() { + return level; + } + + public int getDiscrimminator() { + return discrimminator; + } + } +}