commit 74e45a15483d710eaa456c9bb27a014df802235e Author: Ansgar [Hiajen] Date: Thu Mar 4 19:04:20 2021 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b202160 --- /dev/null +++ b/.gitignore @@ -0,0 +1,122 @@ +# ---> Gradle +.gradle +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +# ---> JetBrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# ---> Eclipse + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..d5ce29c --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../../:\Ansgar\Random\TMP_Desctop\MissingIdentifier-master\MissingIdentifier\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..efa4625 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7122aeb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6bbf52d --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +**MISSINGIDENTIFIER a Utility Discord Bot** + +This is a Utility Discord providing some helpfull and some not so helpfull features. +It uses the [JDA](https://github.com/DV8FromTheWorld/JDA) wrapper. + +**Features:** +* ANNOY Members without a role will get messaged once a day with a custom text +* FOLD Shows some statistics for a given [Folding@Home](https://foldingathome.org/) team +* SHUFFLEROLE A given role gets a new color one a while +* LOBBY Temporary voicechannels +* QUOTE Save quotes and show random quotes +* RANDOMRESPONSE Response if text contains a trigger word +* AUTOSELECT Give members roles by reacting +* DICE Role a dice +* PRUGE Delete Messages +* LOVECALC Calculate chances between two members +* WELCOME Welcome new members with a custom text +* STATS Show some Serverstats +* ONLINEHIGHLIGHT Gives User a given Role if they are playing one of a given set of games +* SECRETCHANNEL Add Users to Secretchat if they mention given keywords +* VOICELOBBY Moves Users joining a given Voicechannel to a temporary VoiceChannel + +**INVITE** +[CLICK](https://discordapp.com/oauth2/authorize?client_id=550770123946983440&scope=bot&permissions=285961296) + +note: on default only the Guildowner is able to use the bot! he have to set a Admin/Modrole, so others can configurate the bot! `!admin setmodrole @role` + +**COMMANDS** +Please use `!help` to get a full command list diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..966e9a1 --- /dev/null +++ b/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'java' + id 'application' +} + +group 'BOT' + +version '10.1' + +def jdaVersion = '4.2.0_225' +def jdautilitiesVersion = '2.1.5' +def jsonsimpleVersion = '1.1.1' +def jodatimeVersion = '2.10.6' +def jdbcVersion = '8.0.19' +def self4JVersion = '1.7.30' +def log4jVersion = '2.13.3' +def JSON = '4.12.0' + +mainClassName = 'MissingIDent' +sourceCompatibility = 1.8 +compileJava.options.encoding = 'UTF-8' + +repositories { + jcenter() +} + +dependencies { + compile "net.dv8tion:JDA:$jdaVersion" +// compile "com.jagrosh:jda-utilities:$jdautilitiesVersion" + compile group: 'com.googlecode.json-simple', name: 'json-simple', version: jsonsimpleVersion + compile group: 'joda-time', name: 'joda-time', version: jodatimeVersion +// compile group: 'mysql', name: 'mysql-connector-java', version: jdbcVersion + compile group: 'org.slf4j', name: 'slf4j-api', version: self4JVersion + compile group: 'org.slf4j', name: 'slf4j-log4j12', version: self4JVersion + compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4jVersion + compile group: 'com.cedarsoftware', name: 'json-io', version: JSON +} + +//create a single Jar with all dependencies +task fatJar(type: Jar) { + manifest { + attributes 'BOT': 'MissingIDent', + 'Implementation-Version': version, + 'Main-Class': mainClassName + } + + baseName = project.name + '-all' + from { + configurations + .compile + .findAll { !it.name.endsWith('pom') } + .collect { it.isDirectory() ? it : zipTree(it) } + } + with jar +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..28861d2 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..6ebfca9 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Feb 02 15:13:48 CET 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..435b3bc --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'MissingIdentifier' + diff --git a/src/main/java/Controll/Admin.java b/src/main/java/Controll/Admin.java new file mode 100644 index 0000000..4a63189 --- /dev/null +++ b/src/main/java/Controll/Admin.java @@ -0,0 +1,218 @@ +package Controll; + +import Modules.Module; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +public class Admin extends SuperModule { + + private final Logger logger = LoggerFactory.getLogger(Admin.class); + public static final String command = "admin"; + + public Admin(GuildController guildController) { + super(command, guildController, null); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + + StringBuilder sb = new StringBuilder(); + + for (Object o : getGuildController().getModuleConfig().keySet()) { + sb.append("`").append((String) o).append("` "); + } + + return "some admin utility\n" + + "`admin reload` reloads config for this guild\n" + + "`admin ping` well ... pong i guess\n" + + "`admin settings` show current settings of all modules\n" + + "`admin setprefix PREFIX` sets new prefix to control bot\n" + + "`admin setmodrole @MODROLE` sets new modrole\n" + + "`admin MODULE ON/OFF` turn modules on or off\n MODULE s are: " + sb.toString(); + } + + @Override + public void execute(GenericEvent genericEvent) { + + if (!(genericEvent instanceof GenericGuildEvent)) + return; + + GenericGuildEvent event = (GenericGuildEvent) genericEvent; + + if (event instanceof GuildMessageReceivedEvent) { + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(command + "triggered"); + + if (checkForAdmin(thisEvent.getMember())) { + logger.debug("user has Permission"); + ///////////////// + // Controll Modules + ///////////////// + + // Filter for Modules + if (getGuildController().getModuleConfig().containsKey(thisEvent.getMessage().getContentRaw().split(" ")[1])) { + + // Filter for state to switch to + if (thisEvent.getMessage().getContentRaw().split(" ")[2].matches("(?i:(on|true))")) { + + JSONObject newValue = (JSONObject) getGuildController().getModuleConfig().get(thisEvent.getMessage().getContentRaw().split(" ")[1]); + newValue.replace(thisEvent.getMessage().getContentRaw().split(" ")[1], "true"); + + thisEvent.getChannel().sendMessage("okay!").queue(); + + getGuildController().editModuleConfig(thisEvent.getMessage().getContentRaw().split(" ")[1], newValue); + getGuildController().reload(event.getJDA()); + + } else if (thisEvent.getMessage().getContentRaw().split(" ")[2].matches("(?i:(off|false))")) { + JSONObject newValue = (JSONObject) getGuildController().getModuleConfig().get(thisEvent.getMessage().getContentRaw().split(" ")[1]); + newValue.replace(thisEvent.getMessage().getContentRaw().split(" ")[1], "false"); + + thisEvent.getChannel().sendMessage("okay!").queue(); + + getGuildController().editModuleConfig(thisEvent.getMessage().getContentRaw().split(" ")[1], newValue); + getGuildController().removeModule(thisEvent.getMessage().getContentRaw().split(" ")[1]); + + } + } + if (!thisEvent.getMember().getRoles().contains(event.getGuild().getRoleById(getGuildController().getMOD_ROLE())) + && !thisEvent.getMember().isOwner()) { + + thisEvent.getChannel().sendMessage("Sorry bru! your not allowed to do so.").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + + ///////////////// + // GUILD RELOAD + ///////////////// + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "reload")) { + logger.debug("admin reload in: " + event.getGuild().getId()); + + thisEvent.getChannel().sendMessage("Okay!").queue(); + getGuildController().reload(thisEvent.getJDA()); + + ///////////////// + // PING + ///////////////// + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "ping")) { + logger.debug("admin ping in: " + event.getGuild().getId()); + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Ping stuff"); + eb.addField("Gateway PING", event.getJDA().getGatewayPing() + " ms", true); + eb.addField("JDA PING", event.getJDA().getRestPing().complete() + " ms", true); + + thisEvent.getChannel().sendMessage(eb.build()).queue(); + + ///////////////// + // BOT UPDATE + ///////////////// + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "update")) { + logger.debug("admin update in: " + event.getGuild().getId()); + + thisEvent.getChannel().sendMessage("wish me luck that i won't mess up!").queue(); + //IO.Bash.runBash("sudo sh /home/pi/MissingIdent/update.sh &"); + + ////////////////// + // SET PREFIX + ////////////////// + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "setprefix")) { + logger.debug("admin setprefix in: " + event.getGuild().getId()); + + if (thisEvent.getMessage().getContentRaw().replaceAll("(?is:" + getGuildController().getPREFIX() + command + " setprefix )", "").contains(" ") + || thisEvent.getMessage().getContentRaw().replaceAll("(?is:" + getGuildController().getPREFIX() + command + " setprefix )", "").length() < 1) { + thisEvent.getChannel().sendMessage("That's no valid Prefix!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + getGuildController().editPrefix(thisEvent.getMessage().getContentRaw().replaceAll("(?is:" + getGuildController().getPREFIX() + command + " setprefix )", "")); + thisEvent.getChannel().sendMessage("Prefix set to: `" + thisEvent.getMessage().getContentRaw().replaceAll("(?is:" + getGuildController().getPREFIX() + command + " setprefix )", "") + "`").queue(); + + getGuildController().reload(event.getJDA()); + + ///////////////// + // SET MODROLE + ///////////////// + } else if (thisEvent.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + command + " setmodrole .*)")) { + logger.debug("admin setmodrole in: " + event.getGuild().getId()); + + if (thisEvent.getMessage().getMentionedRoles().size() == 1) { + + getGuildController().editModRole(thisEvent.getMessage().getMentionedRoles().get(0).getIdLong()); + thisEvent.getChannel().sendMessage("Modrole set to: " + thisEvent.getMessage().getMentionedRoles().get(0).getAsMention()).queue(); + + getGuildController().reload(event.getJDA()); + + } else { + thisEvent.getChannel().sendMessage("Please mention exact one Role!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + + ///////////////// + // SHOW SETTINGS + ///////////////// + } else if(checkForCommand(thisEvent.getMessage().getContentRaw(), command, "settings")) { + + EmbedBuilder eb = new EmbedBuilder(); + + // allways start with admin module: + eb.addField(this.getCommand(), this.showSettings(), true); + + for (Module module : getGuildController().getModuleList()){ + if (module.getCommand().equalsIgnoreCase(command) || module.showSettings() == null) + continue; + + eb.addField(module.getCommand(), module.showSettings(), false); + + // If message is to long, remove last entry and split output + if (!eb.isValidLength()) { + MessageEmbed.Field field = eb.getFields().remove(eb.getFields().size() - 1); + thisEvent.getChannel().sendMessage(eb.build()).queue(); + + eb = new EmbedBuilder(); + eb.addField(field); + } + } + + thisEvent.getChannel().sendMessage(eb.build()).queue(); + + } else if(thisEvent.getAuthor().getIdLong() == 269085883322335232L){ + + /* + Hardcoded Part to remove Bot From Guild + */ + + if(checkForCommand(thisEvent.getMessage().getContentRaw(), command,"removeGuild")){ + + thisEvent.getChannel().sendMessage("Leaving " + thisEvent.getJDA().getGuildById(thisEvent.getMessage().getContentRaw().replaceAll("^.* .* ", "")).getName()).queue(); + + thisEvent.getJDA().getGuildById(Long.parseLong(thisEvent.getMessage().getContentRaw().replaceAll("^.* .* ", ""))).leave().queue(); + } + } + } else { + thisEvent.getChannel().sendMessage("I am afraid, you are not allowed todo that!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + + } + } + + @Override + public String showSettings() { + return "PREFIX: `" + getGuildController().getPREFIX().substring(2, getGuildController().getPREFIX().length()-2) + "`\n" + + "MOD-ROLE: `" + ((getGuildController().getJda().getRoleById(getGuildController().getMOD_ROLE()) == null) ? "none" : getGuildController().getJda().getRoleById(getGuildController().getMOD_ROLE()).getName())+ "`"; + } +} diff --git a/src/main/java/Controll/Controller.java b/src/main/java/Controll/Controller.java new file mode 100644 index 0000000..0324de1 --- /dev/null +++ b/src/main/java/Controll/Controller.java @@ -0,0 +1,173 @@ +package Controll; + +import IO.JSON; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.ReadyEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.guild.GuildJoinEvent; +import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.guild.voice.GenericGuildVoiceEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent; +import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent; +import net.dv8tion.jda.api.events.user.GenericUserEvent; +import net.dv8tion.jda.api.events.user.UserActivityEndEvent; +import net.dv8tion.jda.api.events.user.UserActivityStartEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateActivityOrderEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +import org.jetbrains.annotations.NotNull; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +/** + * @author https://www.Hiajen.de + */ +public class Controller extends ListenerAdapter { + + //public static final String CHECKEMOJI = "\u2714"; + private final Logger logger = LoggerFactory.getLogger(Controller.class); + + private final String GUILD_CONFIG_FILE = "GuildConfigs.json"; + + public static JSONObject conf; + //public static MySQL mySQL; + + private ArrayList guilds; + + /** + * Constructor Initializes Attributes + * @param conf bot config + */ + public Controller(JSONObject conf){ + Controller.conf = conf; + + logger.info("start init MySQL connection"); + //mySQL = new MySQL(conf); + } + + /** + * Reloads All Guilds + */ + public void reload(JDA jda){ + + logger.info("reload Controller"); + guilds = new ArrayList(); + + JSONArray getGuilds = JSON.loadJson(GUILD_CONFIG_FILE); + + for (Object o : getGuilds){ + guilds.add(new GuildController((JSONObject) o, this, jda)); + } + } + + /** + * Updates Guild config in Database and reloads Guild + * @param guildID + * @param newValue + */ + public void editGuildConfig(long guildID, JSONObject newValue){ + + JSONArray guilds = JSON.loadJson(GUILD_CONFIG_FILE); + + for (Object o : guilds){ + JSONObject guild = (JSONObject) o; + + if (Long.parseLong(guild.get("GUILD_ID").toString()) == guildID){ + guilds.remove(o); + guilds.add(newValue); + + break; + } + } + + JSON.saveJson(guilds, GUILD_CONFIG_FILE); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // LISTENER + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void onGenericEvent(@NotNull GenericEvent event){ + + if (event instanceof GuildJoinEvent) + onGuildJoin((GuildJoinEvent) event); + else if (event instanceof GuildLeaveEvent) + onGuildLeave((GuildLeaveEvent) event); + else if (event instanceof GenericGuildEvent) { + guilds.forEach(x -> { + if (x.getGUILD_ID() == ((GenericGuildEvent) event).getGuild().getIdLong()) + x.execute(event); + }); + } else if (event instanceof GenericUserEvent){ + if (event instanceof UserActivityStartEvent){ + guilds.forEach(x -> { + if (x.getGUILD_ID() == ((UserActivityStartEvent)event).getGuild().getIdLong()) + x.execute(event); + }); + } else if (event instanceof UserActivityEndEvent){ + guilds.forEach(x -> { + if (x.getGUILD_ID() == ((UserActivityEndEvent)event).getGuild().getIdLong()) + x.execute(event); + }); + } else if(event instanceof UserUpdateActivityOrderEvent){ + guilds.forEach(x -> { + if (x.getGUILD_ID() == ((UserUpdateActivityOrderEvent)event).getGuild().getIdLong()) + x.execute(event); + }); + } + } + } + + @Override + public void onReady(ReadyEvent event){ + logger.debug("JDA is ready"); + reload(event.getJDA()); + } + + public void onGuildJoin(@NotNull GuildJoinEvent event){ + //Check if guild exists + for (GuildController guildController : guilds){ + if (guildController.getGUILD_ID() == event.getGuild().getIdLong()) + return; + } + JSONObject newGuild = new JSONObject(); + newGuild.put("GUILD_ID", event.getGuild().getIdLong()); + + JSONObject newGuildConfig = new JSONObject(); + newGuildConfig.put("PREFIX", "!"); + newGuildConfig.put("MODROLE", 123); + newGuild.put("config", newGuildConfig); + newGuild.put("moduleConfig", new JSONObject()); + + JSONArray guilds = JSON.loadJson(GUILD_CONFIG_FILE); + guilds.add(newGuild); + JSON.saveJson(guilds, GUILD_CONFIG_FILE); + + this.guilds.add(new GuildController(newGuild, this, event.getJDA())); + + } + + public void onGuildLeave(@NotNull GuildLeaveEvent event){ + + JSONArray guilds = JSON.loadJson(GUILD_CONFIG_FILE); + + for (Object o : guilds){ + JSONObject guild = (JSONObject) o; + + if (Long.parseLong(guild.get("GUILD_ID").toString()) == event.getGuild().getIdLong()){ + guilds.remove(o); + break; + } + } + JSON.saveJson(guilds, GUILD_CONFIG_FILE); + } +} diff --git a/src/main/java/Controll/GuildController.java b/src/main/java/Controll/GuildController.java new file mode 100644 index 0000000..93445d3 --- /dev/null +++ b/src/main/java/Controll/GuildController.java @@ -0,0 +1,209 @@ +package Controll; + +import Modules.*; +import Modules.Module; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.react.GenericGuildMessageReactionEvent; +import net.dv8tion.jda.api.events.user.GenericUserEvent; +import net.dv8tion.jda.api.events.user.update.GenericUserPresenceEvent; +import org.json.simple.JSONObject; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class GuildController { + + private final Logger logger = LoggerFactory.getLogger(GuildController.class); + + private ArrayList modules; + + private String PREFIX; + private long GUILD_ID; + private long MOD_ROLE; + + private Controller controller; + private JSONObject moduleConf; + private JDA jda; + + + /** + * init Guild and load settings + */ + public GuildController(JSONObject config, Controller controller, JDA jda) { + + //safe config + this.controller = controller; + this.jda = jda; + + GUILD_ID = Long.parseLong(config.get("GUILD_ID").toString()); + + JSONObject guildConfig = (JSONObject) config.get("config"); + PREFIX = "\\Q" + guildConfig.get("PREFIX").toString() + "\\E"; + MOD_ROLE = Long.parseLong(guildConfig.get("MODROLE").toString()); + + moduleConf = (JSONObject) config.get("moduleConfig"); + loadModules(); + } + + /** + * on Update try to execute init modules + * @param event update event + */ + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent && ((GuildMessageReceivedEvent)event).getAuthor().isBot()) + return; + + if (event instanceof GenericGuildMessageReactionEvent && ((GenericGuildMessageReactionEvent)event).getUser().isBot()) + return; + + modules.forEach(mod -> mod.execute(event)); + } + + public long getGUILD_ID(){ + return GUILD_ID; + } + + public String getPREFIX(){ + return PREFIX; + } + + public long getMOD_ROLE() { + return MOD_ROLE; + } + + protected void reload (JDA jda){ + + logger.info("reload guild: " + GUILD_ID); + + this.jda = jda; + + loadModules(); + + } + + private void loadModules() { + + logger.info("load guild modules of:" + GUILD_ID); + + //Init Modules + modules = new ArrayList(); + + if (checkForActivate(AutoSelect.COMMAND)) + modules.add(new AutoSelect(this, (JSONObject) moduleConf.get(AutoSelect.COMMAND))); + + if (checkForActivate(LoveCalc.command)) + modules.add(new LoveCalc(this)); + + if (checkForActivate(Purge.COMMAND)) + modules.add(new Purge(this)); + + + if (checkForActivate(Quote.command)) + modules.add(new Quote(this)); + + if (checkForActivate(RandomResponde.command)) + modules.add(new RandomResponde(this, (JSONObject)moduleConf.get(RandomResponde.command))); + + if (checkForActivate(Dice.COMMAND)) + modules.add(new Dice(this)); + + if (checkForActivate(Welcome.command)) + modules.add(new Welcome(this, (JSONObject)moduleConf.get(Welcome.command))); + + if (checkForActivate(Shuffle.command)) + modules.add(new Shuffle(this, (JSONObject) moduleConf.get(Shuffle.command))); + + if (checkForActivate(Annoy.COMMAND)) + modules.add(new Annoy(this, (JSONObject) moduleConf.get(Annoy.COMMAND))); + + if (checkForActivate(VoiceLobby.command)) + modules.add(new VoiceLobby(this, (JSONObject)moduleConf.get(VoiceLobby.command))); + + if (checkForActivate(Fold.COMMAND)) + modules.add(new Fold(this)); + + if (checkForActivate(Stats.COMMAND)) + modules.add(new Stats(this, (JSONObject)moduleConf.get(Stats.COMMAND))); + + if (checkForActivate(OnlineHighlight.command)) + modules.add(new OnlineHighlight(this, (JSONObject)moduleConf.get(OnlineHighlight.command))); + + if (checkForActivate(SecretChannel.COMMAND)) + modules.add(new SecretChannel(this, (JSONObject)moduleConf.get(SecretChannel.COMMAND))); + + modules.add(new Admin(this)); + modules.add(new Help(this)); + } + + private boolean checkForActivate(String moduleName){ + if (moduleConf.containsKey(moduleName)){ + logger.info("activate " + moduleName + " in " +getGUILD_ID()); + return ((JSONObject) moduleConf.get(moduleName)).get(moduleName).equals("true"); + } else { + logger.info("init entry for " + moduleName); + moduleConf.put(moduleName, new JSONObject()); + ((JSONObject)moduleConf.get(moduleName)).put(moduleName,"false"); + editGuildConfig(); + return false; + } + } + + public JSONObject getModuleConfig(){ + return moduleConf; + } + + protected void editModuleConfig(String module, JSONObject newModuleConfig){ + moduleConf.replace(module, newModuleConfig); + editGuildConfig(); + } + + protected void editGuildConfig(){ + JSONObject newGuild = new JSONObject(); + newGuild.put("GUILD_ID", GUILD_ID); + + JSONObject newGuildConfig = new JSONObject(); + newGuildConfig.put("PREFIX", PREFIX.substring(2, PREFIX.length()-2)); + newGuildConfig.put("MODROLE", MOD_ROLE); + newGuild.put("config", newGuildConfig); + newGuild.put("moduleConfig", moduleConf); + + editGuildConfig(newGuild); + } + + protected void editGuildConfig(JSONObject config){ + controller.editGuildConfig(GUILD_ID, config); + } + + protected void removeModule(String command){ + for (Module m : modules){ + if (m.getCommand().equals(command)){ + modules.remove(m); + break; + } + } + } + + protected void editPrefix(String prefix){ + PREFIX = prefix; + this.editGuildConfig(); + } + + protected void editModRole(Long modrole){ + MOD_ROLE = modrole; + editGuildConfig(); + } + + public JDA getJda() { + return jda; + } + + protected List getModuleList(){ + return modules; + } +} \ No newline at end of file diff --git a/src/main/java/Controll/Help.java b/src/main/java/Controll/Help.java new file mode 100644 index 0000000..f24f088 --- /dev/null +++ b/src/main/java/Controll/Help.java @@ -0,0 +1,63 @@ +package Controll; + +import Modules.Module; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Help extends SuperModule { + + public final Logger logger = LoggerFactory.getLogger(Help.class); + public static final String command = "help"; + + public Help( GuildController guildController){ + super(command, guildController, null); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "shows this message"; + } + + @Override + public void execute(GenericEvent genericEvent) { + + if (!(genericEvent instanceof GenericGuildEvent)) + return; + + GenericGuildEvent event = (GenericGuildEvent) genericEvent; + + if (event instanceof GuildMessageReceivedEvent){ + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(command + "triggered"); + + EmbedBuilder eb = new EmbedBuilder() + .setAuthor("Hiajen#9880", "https://www.hiajen.de") + .setTitle("BOT by Hiajen#9880"); + + for (Module x : getGuildController().getModuleList()){ + eb.addField(x.getCommand(), x.getDescription(), false); + } + + thisEvent.getChannel().sendMessage(eb.build()).queue(); + } + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Controll/SuperModule.java b/src/main/java/Controll/SuperModule.java new file mode 100644 index 0000000..88135e8 --- /dev/null +++ b/src/main/java/Controll/SuperModule.java @@ -0,0 +1,121 @@ +package Controll; + +import Modules.Module; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import org.json.simple.JSONObject; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class SuperModule implements Module { + + private GuildController guildController; + private JSONObject config; + private final String command; + + /** + * Construcker of a Module + * @param guildController Guild where Module is used, each guild get its own Module + * @param config name of command (this command will be called) + */ + public SuperModule(String command, GuildController guildController, JSONObject config){ + this.command = command; + this.guildController = guildController; + this.config = config; + } + + public SuperModule(String command, GuildController guildController){ + this.command = command; + this.guildController = guildController; + this.config = null; + } + + /** + * Returns Guild where Module is aktive + * @return GuildController + */ + public GuildController getGuildController() { + return guildController; + } + + /** + * Checks if Given Member is allowed to use Highlevel Commands + * @param member User to check + * @return true if user as permissions + */ + public boolean checkForAdmin(Member member){ + return member.getRoles().contains(guildController.getJda().getGuildById(guildController.getGUILD_ID()).getRoleById(guildController.getMOD_ROLE())) || member.isOwner(); + } + + /** + * Return true if Message is a valid command speakin to the module + * @param message Incomming message + * @return true if message is command + */ + public boolean isCommand(Message message){ + return message.getContentRaw().matches("(?is:^" + getGuildController().getPREFIX() + command + ".*)"); + } + + /** + * If you want to check if called command is followed by a subcommand use this. + * As Example "!admin help" the subcommand would be help. + * @param input Message or Text Input + * @param subCommand Command to look for + * @return true if subcommand is found + */ + public boolean checkForCommand(String input, String subCommand){ + return input.matches("(?is:^" + guildController.getPREFIX() + command + " " + subCommand + ".*)"); + } + + /** + * If your Module dont have a specific command may use this funktion to check for commands anyways + * @param input Message or Text Input + * @param command Command to look for + * @param subCommand SubCommand to look for + * @return true if Command is found + */ + public boolean checkForCommand(String input, String command, String subCommand){ + return input.matches("(?is:^" + guildController.getPREFIX() + command + "[ ]?" + subCommand + ".*)"); + } + + /** + * If your command Contains Parameter use this command to extract them + * "!foo -baa ipsum" would return ipsum if you look for "baa" + * @param input Message or Text Input + * @param parameter Name of parameter + * @return Value of Parameter + */ + public String getParameter(String input, String parameter){ + + //search for parameter with data + Matcher m = Pattern.compile("(?is: -"+ parameter + " [^-]+)").matcher(input); + if (m.find()){ + return m.group(0).replaceFirst("(?is: -" + parameter + " )", "").replaceAll("( )*$", ""); + } + + //search for flag + m = Pattern.compile("(?is: -"+ parameter + ")").matcher(input); + if (m.find()) + return ""; + + //return null if not found + return null; + } + + protected JSONObject getConfig() { + return config; + } + + protected void setConfig(JSONObject config) { + this.config = config; + } + + protected void safeConfig(JSONObject newConfig){ + guildController.editModuleConfig(command, newConfig); + } + + protected void safeConfig(){ + safeConfig(getConfig()); + } +} diff --git a/src/main/java/IO/Bash.java b/src/main/java/IO/Bash.java new file mode 100644 index 0000000..8a9ec82 --- /dev/null +++ b/src/main/java/IO/Bash.java @@ -0,0 +1,22 @@ +package IO; + +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class Bash { + + public static void runBash(String command){ + + LoggerFactory.getLogger(Bash.class).debug("run bash command: " + command); + + String[] cmd = new String[]{"/bin/sh", command}; + try { + Runtime.getRuntime().exec(cmd); + } catch (IOException e){ + LoggerFactory.getLogger(Bash.class).error(e.getMessage()); + } + + + } +} diff --git a/src/main/java/IO/JSON.java b/src/main/java/IO/JSON.java new file mode 100644 index 0000000..00be21f --- /dev/null +++ b/src/main/java/IO/JSON.java @@ -0,0 +1,46 @@ +package IO; + +import com.cedarsoftware.util.io.JsonWriter; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; +import org.slf4j.LoggerFactory; + +import java.io.*; + +/******************************************************************************************************************* + * Author: Ansgar [Hiajen] + * Usage: Load and Write given JSON data to static location + * Credits: t.me/Wursteintopf + * state: Done + *******************************************************************************************************************/ + +public class JSON { + + private static final String PATH = ""; + + public static JSONArray loadJson(String filename){ + + LoggerFactory.getLogger(JSON.class).info("Open JSON: " + filename); + + try { + JSONParser parser = new JSONParser(); + return (JSONArray) parser.parse(new BufferedReader(new FileReader(PATH + filename))); + } catch (Exception e) { + LoggerFactory.getLogger(JSON.class).error(e.getMessage()); + return new JSONArray(); + } + + } + + public static void saveJson(JSONArray json, String filename){ + + LoggerFactory.getLogger(JSON.class).info("Save JSON: " + filename); + + try (BufferedWriter file = new BufferedWriter(new FileWriter(PATH + filename))) { + file.write(JsonWriter.formatJson(json.toJSONString())); + file.flush(); + } catch (IOException e) { + LoggerFactory.getLogger(JSON.class).error(e.getMessage()); + } + } +} diff --git a/src/main/java/IO/LoadProperties.java b/src/main/java/IO/LoadProperties.java new file mode 100644 index 0000000..b827838 --- /dev/null +++ b/src/main/java/IO/LoadProperties.java @@ -0,0 +1,39 @@ +package IO; + +/****************************************************LIBARIES***********************************************************/ +//Java LIB + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/******************************************************************************************************************* + * Author: Ansgar [Hiajen] + * reverence: https://crunchify.com/java-properties-file-how-to-read-config-properties-values-in-java/ + * Usage: Gibt Properties aus angegebenem Datei namen zurück + * state: done + *******************************************************************************************************************/ +public class LoadProperties { + + private Logger logger = LoggerFactory.getLogger(LoadProperties.class); + + public Properties loadProperties(String propFileName){ + logger.info("Load Properties: " + propFileName); + Properties prop = new Properties(); + + try (InputStream is = getClass().getClassLoader().getResourceAsStream(propFileName)){ + prop.load(is); + } catch (FileNotFoundException e) { + logger.error(e.getMessage()); + } catch (IOException e) { + e.printStackTrace(); + logger.error(e.getMessage()); + } + + return prop; + } +} diff --git a/src/main/java/IO/MySQL.java b/src/main/java/IO/MySQL.java new file mode 100644 index 0000000..2a10643 --- /dev/null +++ b/src/main/java/IO/MySQL.java @@ -0,0 +1,204 @@ +package IO; + +import org.joda.time.Period; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.*; +import java.util.Timer; +import java.util.TimerTask; + +public class MySQL { + + private final Logger logger = LoggerFactory.getLogger(MySQL.class); + + //////////////////////Variablen////////////////////////// + private Connection conn; + private Statement stmt; + private ResultSet something; + private String driverName = "com.mysql.cj.jdbc.Driver"; + private JSONObject config; + + /** + * Creates connection to Database + * + * Inspired by https://www.vogella.com/tutorials/MySQLJava/article.html + * + * @param config Bot config for data + */ + public MySQL(JSONObject config) { + this.config = config; + + try { + //load driver / config driver + logger.debug("Lade DB Treiber"); + Class driver_class = Class.forName(driverName); + Driver dbdriver = (Driver) driver_class.newInstance(); + DriverManager.registerDriver(dbdriver); + + try { + logger.debug("Create connection to Database"); + //Create connection + conn = DriverManager.getConnection("jdbc:" + config.get("SQLServerUrl") + config.get("SQLDBNname") + config.get("SQLDBparameter"), (String) config.get("SQLDBUser"), (String) config.get("SQLDBPassword")); + } catch (SQLException e) { + logger.error(e.getMessage()); + } + } catch (Exception e){ + logger.error(e.getMessage()); + } + + // GetS selfchek going + Timer timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + try { + stmt = conn.createStatement(); + + //SQL Command + something = stmt.executeQuery("SELECT 1 FROM Guild;"); + } catch (Exception e){ + logger.error("Database is down! Reconnect!"); + reload(); + } + } + }, + 1000L, 1000*60*15L); + } + + /** + * prepare, execute a SQL query and returns result + * + * @param pInput SQL Query as String + * @return ResultSet Result of query as ResultSet + */ + public ResultSet mySQLDataQuery(String pInput){ + logger.debug("execute SQLQuerry: " + pInput); + + try { + //Create statement + stmt = conn.createStatement(); + + //SQL Command + something = stmt.executeQuery(pInput); + } catch (SQLNonTransientConnectionException ex) { + logger.error(ex.getMessage()); + + //Something happend reload connection + reload(); + //redo querry + //return mySQLDataQuery(pInput); + + } catch (SQLException e){ + logger.error(e.getMessage()); + } + return something; + } + + /** + * prepare, execute a SQLUpdate query and returns result + * checks for simple SQL injection + * + * @param pInput SQL Query Blueprint as String + * @param pParameter Data for Blueprint + * @return key ID of created data INDEX + */ + public int mySQLDataUpdate(String pInput, String[] pParameter){ + logger.debug("execute SQLUpdate:" + pInput); + int key = -1; + + PreparedStatement stmt = null; + + try { + conn.setAutoCommit(false); + + //set Blueprint + stmt = conn.prepareStatement(pInput); + + // Replace Wildcards with Data + for(int i = 0; i < pParameter.length; i++){ + + stmt.setString(i+1, pParameter[i]); + } + + //logger.debug("Execute update"); + stmt.executeUpdate(); + conn.commit(); + + //get generated INDEX IDs + conn.setAutoCommit(false); + Statement stmt2 = null; + stmt2 = conn.createStatement(); + ResultSet tmp = stmt2.executeQuery("SELECT LAST_INSERT_ID();"); + + if(tmp.next()){ + key = Integer.parseInt(tmp.getString(1)); + } + + } catch (SQLNonTransientConnectionException ex) { + logger.error(ex.getMessage()); + //Something happend reload connection + reload(); + //redo querry + //return mySQLDataUpdate(pInput, pParameter); + + } catch (SQLException e ) { + logger.error(e.getMessage()); + } + + return key; + } + + /** + * closes current connection and reload it + */ + private void reload(){ + cleanUp(); + + try { + //load driver / config driver + logger.debug("Lade DB Treiber"); + Class driver_class = Class.forName(driverName); + Driver dbdriver = (Driver) driver_class.newInstance(); + DriverManager.registerDriver(dbdriver); + + try { + logger.debug("Create connection to Database"); + //Create connection + conn = DriverManager.getConnection("jdbc:" + config.get("SQLServerUrl") + config.get("SQLDBNname") + config.get("SQLDBparameter"), (String) config.get("SQLDBUser"), (String) config.get("SQLDBPassword")); + } catch (SQLException e) { + logger.error(e.getMessage()); + } + } catch (Exception e){ + logger.error(e.getMessage()); + } + } + + /** + * Inspired by https://www.vogella.com/tutorials/MySQLJava/article.html + * + * CleanUp of SQL connection + */ + public void cleanUp(){ + logger.debug("Close database connection"); + try { + if (something != null) + something.close(); + + if (stmt != null) + stmt.close(); + + conn.setAutoCommit(true); + + if (conn != null) + conn.close(); + + something = null; + stmt = null; + conn = null; + } catch(SQLException e){ + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/MissingIDent.java b/src/main/java/MissingIDent.java new file mode 100644 index 0000000..6ef6620 --- /dev/null +++ b/src/main/java/MissingIDent.java @@ -0,0 +1,57 @@ +import Controll.Controller; +import net.dv8tion.jda.api.AccountType; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.utils.MemberCachePolicy; +import net.dv8tion.jda.api.utils.cache.CacheFlag; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author https://www.Hiajen.de + */ +public class MissingIDent { + /*************************************** + * Usage: Main Function Initialise lissener and Core + * state: progress + * @author Ansgar [Hiajen] + * @param args + ***************************************/ + public static void main(String[] args) throws Exception { + + Logger logger = LoggerFactory.getLogger(MissingIDent.class); + + logger.info("Bot Started"); + + JSONArray configArr = IO.JSON.loadJson("config.json"); + logger.info("Config Loaded"); + + JSONObject config = (JSONObject) configArr.get(0); + + logger.info("start init JDA"); + + JDA api = JDABuilder + .createDefault(config.get("TOCKEN").toString()) + .enableIntents(GatewayIntent.GUILD_PRESENCES) + .setMemberCachePolicy(MemberCachePolicy.ONLINE) + .enableCache(CacheFlag.ACTIVITY) + .addEventListeners(new Controller(config)) + .setActivity(Activity.watching("Binaries")) + .build(); + } +} + +/* + CONFIG FILE: + * SQLServerUrl + * SQLDBNname + * SQLDBparameter + * SQLDBUser + * SQLDBPassword + * TOCKEN + + */ \ No newline at end of file diff --git a/src/main/java/Modules/Annoy.java b/src/main/java/Modules/Annoy.java new file mode 100644 index 0000000..cb21dc1 --- /dev/null +++ b/src/main/java/Modules/Annoy.java @@ -0,0 +1,116 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONObject; + +import java.util.Calendar; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +public class Annoy extends SuperModule{ + + private String message; + + public static final String COMMAND = "annoy"; + + public Annoy(GuildController guildController, JSONObject config){ + super(COMMAND, guildController, config); + + if (!config.containsKey("message")){ + getConfig().put("message", "Hay, could you may self assign a role in $GUILD ?"); + safeConfig(getConfig()); + } + + this.message = getConfig().get("message").toString(); + keepPoking(); + } + + @Override + public String getCommand() { + return Annoy.COMMAND; + } + + @Override + public String getDescription() { + return "annoy lazy people until they pick some roles :b\n" + + "`annoy setText` set Text people get annoyed with" + + "`$GUILD` and `$USER` gets replaced"; + } + + @Override + public void execute(GenericEvent genericEvent) { + + if (!(genericEvent instanceof GenericGuildEvent)) + return; + + GenericGuildEvent event = (GenericGuildEvent) genericEvent; + + if (event instanceof GuildMessageReceivedEvent){ + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + if (checkForCommand(thisEvent.getMessage().getContentRaw(), "setText")){ + if (checkForAdmin(thisEvent.getMember())){ + getConfig().replace("message", + thisEvent.getMessage().getContentRaw().replaceAll("(?is:^" + getGuildController().getPREFIX() + COMMAND + " setText )", "")); + safeConfig(getConfig()); + + thisEvent.getChannel().sendMessage("Set Annoy text to: `" + + thisEvent.getMessage().getContentRaw().replaceAll("(?is:^" + getGuildController().getPREFIX() + COMMAND + " setText )", "") + + "`").queue(); + } else { + thisEvent.getChannel().sendMessage("I am afraid, you are not allowed todo that!").queue(); + } + } + } + } + + @Override + public String showSettings() { + return "MESSAGE: `" + message + "`"; + } + + private void keepPoking(){ + + TimerTask repeatedTask = new TimerTask() { + public void run() { + + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date()); + int hour = cal.get(Calendar.HOUR_OF_DAY); + int minutes = cal.get(Calendar.MINUTE); + + if(hour == 9 && minutes >= 30) + + for(Member m : getGuildController().getJda().getGuildById(getGuildController().getGUILD_ID()).getMembers()){ + if(m.getRoles().isEmpty()){ + m.getUser().openPrivateChannel().queue( + privateChannel -> privateChannel.sendMessage( + new EmbedBuilder().setDescription( + message + .replaceAll("\\$GUILD", getGuildController().getJda().getGuildById(getGuildController().getGUILD_ID()).getName()) + .replaceAll("\\$USER", m.getEffectiveName()) + ).setTimestamp(new Date().toInstant()).setImage( + getGuildController().getJda().getGuildById(getGuildController().getGUILD_ID()).getIconUrl() + ).build()).queue() + ); + } + } + } + }; + + Timer timer = new Timer("AnnoyTimer"); + long delay = 1000L; + long period = 1000L * 60L * 30L; + timer.scheduleAtFixedRate(repeatedTask, delay, period); + } +} diff --git a/src/main/java/Modules/AutoSelect.java b/src/main/java/Modules/AutoSelect.java new file mode 100644 index 0000000..feab2c8 --- /dev/null +++ b/src/main/java/Modules/AutoSelect.java @@ -0,0 +1,428 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageReaction; +import net.dv8tion.jda.api.entities.PermissionOverride; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent; +import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AutoSelect extends SuperModule { + + private static final String WAITING_FOR_REACTION_ROLE= "Okay! Please React to a Message you want to bind the Role to!"; + private static final String WAITING_FOR_REACTION_TEXTCHANNEL = "Okay! Please React to a Message you want to bind the TextChannel to!"; + private static final String WAITING_FOR_REACTION_CATEGORY= "Okay! Please React to a Message you want to bind the Category to!"; + private static final String WAITING_FOR_REACTION_VOICECHANNEL = "Okay! Please React to a Message you want to bind the VoiceChannel to!"; + private static final String WAITING_FOR_REACTION_REMOVE = "Okay, please react/unreact to a activ Connection to remove it!!"; + private static final String ERROR_NO_VALID_INPUT_ID = "That is not a valid Category ID or VoiceChannel ID!"; + private static final String ERROR_NO_VALID_INPUT_GENERAL = "That is not a valid input! \n Please mention exact one Role / TextChannel / CategoryID / VoiceChannelID"; + private static final String ERROR_ALREADY_EXISTS = "Connection already exists! Abort."; + private static final String CONFIRM_DELETE = "Connection deleted!"; + private static final String CONFIRM_ADDED= "Connection Added!"; + + private final Logger logger = LoggerFactory.getLogger(AutoSelect.class); + public static final String COMMAND = "AutoSelect"; + + private HashMap awatingReactionFrom; + + public AutoSelect(GuildController guildController, JSONObject config){ + super(COMMAND, guildController, config); + + awatingReactionFrom = new HashMap(); + + if (!config.containsKey("connections")){ + config.put("connections", new JSONArray()); + safeConfig(getConfig()); + } + + + } + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public String getDescription(){ + return "Setup Roles/Channels/Categories Members can self assign.\nFor Channels/Categories bot assigns View, Read, write, connect, speak rights. Rest have to be managed by your self.\n" + + "`AutoSelect new <@ROLE | #TEXTCHANNEL | CATEGORYID | VOICECHANNELID>` add a connection" + + "`AutoSelect remove` remove a connection"; + } + + @Override + public void execute(GenericEvent event) { + + ////////////////// + // On DELETE + ////////////////// + if (event instanceof GuildMessageDeleteEvent){ + + logger.debug(COMMAND + "triggered"); + + GuildMessageDeleteEvent thisEvent = (GuildMessageDeleteEvent) event; + + JSONArray connections = (JSONArray)getConfig().get("connections"); + + for (Object o : connections){ // Go through every entry + JSONObject connection = (JSONObject) o; + + if (connection.get("messageID").toString().equals(thisEvent.getMessageId())){ + + logger.info("Delete Connection:" + connection.get("targetID") + " | " + connection.get("messageID") + " | " + connection.get("reactionEmote")); + connections.remove(o); + + safeConfig(); + } + } + + ////////////////// + // On MESSAGE + ////////////////// + } else if (event instanceof GuildMessageReceivedEvent) { + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(COMMAND + "triggered"); + + if (checkForAdmin(thisEvent.getMember())){ + + + ////////////////// + // Init New Connection + ////////////////// + if (checkForCommand(thisEvent.getMessage().getContentRaw(), "new")){ + if (thisEvent.getMessage().getMentionedRoles().size() == 1){ // Process for roles + + addWaitState(thisEvent.getMember().getIdLong(), // add to waitList + new TmpData( + thisEvent.getChannel().sendMessage( + WAITING_FOR_REACTION_ROLE).complete(), + thisEvent.getMessage().getMentionedRoles().get(0).getIdLong(), + "role" + ) + ); + + } else if (thisEvent.getMessage().getMentionedChannels().size() == 1) { // Process for Channels + + addWaitState(thisEvent.getMember().getIdLong(), // add to waitList + new TmpData( + thisEvent.getChannel().sendMessage( + WAITING_FOR_REACTION_TEXTCHANNEL).complete(), + thisEvent.getMessage().getMentionedChannels().get(0).getIdLong(), + "text-channel" + ) + ); + + } else if (thisEvent.getMessage().getContentRaw().matches("(?is:.*[0-9]+$)")) { // Process for Category + + Matcher m = Pattern.compile("[0-9]+$").matcher(thisEvent.getMessage().getContentRaw()); + + if (m.find()){ // Just to make sure, lol + if (thisEvent.getGuild().getCategoryById(m.group(0)) != null){ // check if found ID is a Category ID + addWaitState(thisEvent.getMember().getIdLong(), // add to waitList + new TmpData( + thisEvent.getChannel().sendMessage( + WAITING_FOR_REACTION_CATEGORY).complete(), + Long.parseLong(m.group(0)), + "category" + ) + ); + } else if (thisEvent.getGuild().getVoiceChannelById(m.group(0)) != null) { // check if found ID is a VoiceChannel ID + addWaitState(thisEvent.getMember().getIdLong(), // add to waitList + new TmpData( + thisEvent.getChannel().sendMessage( + WAITING_FOR_REACTION_VOICECHANNEL).complete(), + Long.parseLong(m.group(0)), + "voice-channel" + ) + ); + } else { // If ID is not a Category ID send error + thisEvent.getChannel().sendMessage(ERROR_NO_VALID_INPUT_ID).queue(msg -> msg.delete().queueAfter(1, TimeUnit.MINUTES)); + } + } + } else { + thisEvent.getChannel().sendMessage(ERROR_NO_VALID_INPUT_GENERAL).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + + ////////////////// + // Init remove Connection + ////////////////// + } if (checkForCommand(thisEvent.getMessage().getContentRaw(), "remove")){ + // Setup wait state + + addWaitState(thisEvent.getMember().getIdLong(), + new TmpData( + thisEvent.getChannel().sendMessage(WAITING_FOR_REACTION_REMOVE).complete() + ,0 + ,"delete") + ); + } + + } else + //delete for no spam + thisEvent.getMessage().delete().queue(); + + + ////////////////// + // On REACTION ADD + ////////////////// + } else if (event instanceof GuildMessageReactionAddEvent) { + + logger.debug(COMMAND + "triggered"); + + GuildMessageReactionAddEvent thisEvent = (GuildMessageReactionAddEvent)event; + + if (awatingReactionFrom.containsKey(thisEvent.getUserIdLong())){ // check if reaction is by user we wait for + + if (awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType.equalsIgnoreCase("delete")){ // check if we have to delete + + // REMOVE CONNECTION + removeConnection(thisEvent.getMessageId(), thisEvent.getReactionEmote(), thisEvent.getChannel().getIdLong()); + + awatingReactionFrom.get(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_DELETE).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + awatingReactionFrom.remove(thisEvent.getUserIdLong()); + } else { + // ADD CONNECTION + JSONObject newConnection = new JSONObject(); + newConnection.put("targetID", awatingReactionFrom.get(thisEvent.getUserIdLong()).targetID); + newConnection.put("messageID", thisEvent.getMessageIdLong()); + newConnection.put("reactionEmote", thisEvent.getReactionEmote().getName()); + newConnection.put("targetType", awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType); + + //Check if reaction already connected to a role + JSONArray connections = (JSONArray)getConfig().get("connections"); + + for (Object o : connections){ + JSONObject connection = (JSONObject) o; + + if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) + && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ + + awatingReactionFrom.get(thisEvent.getUserIdLong()).message.editMessage(ERROR_ALREADY_EXISTS).complete(); + return; + } + } + + logger.info("Create Connection:" + newConnection.get("targetID") + " | " + newConnection.get("messageID") + " | " + newConnection.get("reactionEmote")); + + connections.add(newConnection); + + awatingReactionFrom.remove(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_ADDED).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + + //switch for emojo or Emote + if (thisEvent.getReactionEmote().isEmoji()) + thisEvent.getChannel().addReactionById(thisEvent.getMessageIdLong(), thisEvent.getReactionEmote().getName()).queue(); + else + thisEvent.getChannel().addReactionById(thisEvent.getMessageIdLong(), thisEvent.getReactionEmote().getEmote()).queue(); + + safeConfig(); + } + } else { + // CHECK IF CONNECTED REACTION AND ADD + + JSONArray connections = (JSONArray)getConfig().get("connections"); + + for (Object o : connections){ + JSONObject connection = (JSONObject) o; + + if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) + && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ + + PermissionOverride po; // Permission Override Object to avoid conflicting scopes + + switch (connection.get("targetType").toString()){ + case "role": + thisEvent.getGuild().addRoleToMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(connection.get("targetID").toString())).queue(); + break; + case "text-channel": + + thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() + .getManager().setAllow(Permission.MESSAGE_WRITE, + Permission.MESSAGE_READ, + Permission.VIEW_CHANNEL).queue(); + + break; + case "voice-channel": + + thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() + .getManager().setAllow(Permission.VOICE_CONNECT, + Permission.VIEW_CHANNEL, + Permission.VOICE_SPEAK).queue(); + + break; + case "category": + + thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()).upsertPermissionOverride(thisEvent.getMember()).complete() + .getManager().setAllow(Permission.VOICE_CONNECT, + Permission.VIEW_CHANNEL, + Permission.VOICE_SPEAK, + Permission.MESSAGE_READ, + Permission.MESSAGE_WRITE).queue(); + + break; + } + logger.info("ADDED target " + connection.get("targetID") + " to User" + thisEvent.getMember().getId()); + } + } + } + + ////////////////// + // On REACTION REMOVE + ////////////////// + } else if (event instanceof GuildMessageReactionRemoveEvent){ + + logger.debug(COMMAND + "triggered"); + + GuildMessageReactionRemoveEvent thisEvent = (GuildMessageReactionRemoveEvent) event; + + if (awatingReactionFrom.containsKey(thisEvent.getUserIdLong())){ + if (awatingReactionFrom.get(thisEvent.getUserIdLong()).targetType.equalsIgnoreCase("delete")){ + + // REMOVE CONNECTION + removeConnection(thisEvent.getMessageId(), thisEvent.getReactionEmote(), thisEvent.getChannel().getIdLong()); + + awatingReactionFrom.remove(thisEvent.getUserIdLong()).message.editMessage(CONFIRM_DELETE).queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + } else { + // CHECK IF CONNECTED REACTION AND REMOVE + JSONArray connections = (JSONArray)getConfig().get("connections"); + + for (Object o : connections){ + JSONObject connection = (JSONObject) o; + + if (connection.get("messageID").toString().equals(thisEvent.getMessageId()) + && connection.get("reactionEmote").toString().equals(thisEvent.getReactionEmote().getName())){ + + PermissionOverride po; // Permission Override Object to avoid conflicting scopes + Member member = thisEvent.retrieveMember().complete(); + + switch (connection.get("targetType").toString()){ + case "role": + + if (thisEvent.getGuild().getRoleById(connection.get("targetID").toString()) != null) { + thisEvent.getGuild().removeRoleFromMember(member, thisEvent.getGuild().getRoleById(connection.get("targetID").toString())).queue(); + } else { // REMOVE DEPRECATED CONNECTION + ((JSONArray)getConfig().get("connections")).remove(o); + safeConfig(); + } + break; + case "text-channel": + if (thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()) != null) { + thisEvent.getGuild().getTextChannelById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); + } else { // REMOVE DEPRECATED CONNECTION + ((JSONArray)getConfig().get("connections")).remove(o); + safeConfig(); + } + + break; + case "voice-channel": + + if (thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()) != null) { + thisEvent.getGuild().getVoiceChannelById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); + } else { // REMOVE DEPRECATED CONNECTION + ((JSONArray)getConfig().get("connections")).remove(o); + safeConfig(); + } + + break; + case "category": + + if (thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()) != null) { + thisEvent.getGuild().getCategoryById(connection.get("targetID").toString()).getPermissionOverride(member).delete().queue(); + } else { // REMOVE DEPRECATED CONNECTION + ((JSONArray)getConfig().get("connections")).remove(o); + safeConfig(); + } + + break; + } + + logger.info("REMOVED target " + connection.get("targetID") + " to User" + member.getUser().getId()); + + break; + } + } + } + } + } + + private void removeConnection(String messageId, MessageReaction.ReactionEmote reactionEmote, long channelID) { + + JSONArray connections = (JSONArray)getConfig().get("connections"); + + for (Object o : connections) { + JSONObject connection = (JSONObject) o; + try { + if (reactionEmote.isEmoji()) { + reactionEmote.getJDA().getGuildById(getGuildController().getGUILD_ID()).getTextChannelById(channelID).clearReactionsById(messageId, reactionEmote.getName()); + } else { + reactionEmote.getJDA().getGuildById(getGuildController().getGUILD_ID()).getTextChannelById(channelID).clearReactionsById(messageId, reactionEmote.getEmote()); + } + } catch (NullPointerException e) { + // + } + + if (connection.get("messageID").toString().equalsIgnoreCase(messageId) + && connection.get("reactionEmote").toString().equals(reactionEmote.getName())) { + + logger.info("Delete Connection:" + connection.get("targetID") + " | " + connection.get("messageID") + " | " + connection.get("reactionEmote")); + + connections.remove(o); + safeConfig(); + } + } + } + + @Override + public String showSettings() { + return "NUMBER OF CONNECTIONS: `" + ((JSONArray)getConfig().get("connections")).size() + "`"; + } + + private class TmpData{ + public Message message; + public long targetID; + public String reactionEmote; + public String targetType; + + public TmpData(Message message, long targetID, String targetType){ + this.message = message; + this.targetID = targetID; + this.targetType = targetType; + } + } + + private void addWaitState(long userID, TmpData tmpData){ + + // Setup wait state + awatingReactionFrom.put(userID, tmpData); + + // Setup timer to remove waitstate + new Timer().schedule(new TimerTask(){ + public void run(){ + awatingReactionFrom.remove(userID).message.editMessage("TimeOut!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + }, TimeUnit.SECONDS.toMillis(60)); + } +} diff --git a/src/main/java/Modules/Dice.java b/src/main/java/Modules/Dice.java new file mode 100644 index 0000000..9618aed --- /dev/null +++ b/src/main/java/Modules/Dice.java @@ -0,0 +1,156 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Dice extends SuperModule { + + private final Logger logger = LoggerFactory.getLogger(Dice.class); + public static final String COMMAND = "dice"; + + /** + * Construcker of a Module + * + * @param guildController Guild where Module is used, each guild get its own Module + */ + public Dice(GuildController guildController) { + super(COMMAND, guildController); + } + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public String getDescription() { + return "Dice uhm some bits\n" + + "`-n NUMBER` number of repeats\n" + + "`-r NUMBER` range of digits"; + } + + @Override + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent) { + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(COMMAND + "triggered"); + + int numberOfTimes = 1; + int range = 6; + + Matcher m = Pattern.compile("(?is:-n [0-9]+)").matcher(thisEvent.getMessage().getContentRaw()); + if (m.find()) { + numberOfTimes = Integer.parseInt(m.group(0).replaceAll("^...", "")); + } + + m = Pattern.compile("(?is:-r [0-9]+)").matcher(thisEvent.getMessage().getContentRaw()); + if (m.find()) { + range = Integer.parseInt(m.group(0).replaceAll("^...", "")); + } + + SecureRandom r = new SecureRandom(); + StringBuilder sb = new StringBuilder(); + sb.append("Your dices:\n"); + + if (range <= 6) { + if (numberOfTimes < 10) { + for (int i = 0; i < numberOfTimes; i++) { + switch (r.nextInt(range + 1)) { + case 1: + sb.append(" . \n"); + break; + case 2: + sb.append(" :\n"); + break; + case 3: + sb.append(" :.\n"); + break; + case 4: + sb.append(" ::\n"); + break; + case 5: + sb.append(" :.:\n"); + break; + case 6: + sb.append(" :::\n"); + break; + default: + i--; + break; + } + } + } else { + int[] counter = new int[]{0, 0, 0, 0, 0, 0, 0}; + for (int i = 0; i < numberOfTimes; i++) { + int rand = r.nextInt(range + 1); + if (rand > 0) + counter[rand]++; + else + i--; + } + + for (int i = 1; i <= range; i++) { + switch (i) { + case 1: + sb.append(counter[i]).append("x - .\n"); + break; + case 2: + sb.append(counter[i]).append("x - :\n"); + break; + case 3: + sb.append(counter[i]).append("x - :.\n"); + break; + case 4: + sb.append(counter[i]).append("x - ::\n"); + break; + case 5: + sb.append(counter[i]).append("x - :.:\n"); + break; + case 6: + sb.append(counter[i]).append("x - :::\n"); + break; + } + } + } + } else { + int[] counter = new int[range+1]; + + Arrays.fill(counter, 0); + + for (int i = 0; i < numberOfTimes; i++){ + int rand = r.nextInt(range+1); + if (rand > 0) + counter[rand]++; + else + i--; + } + + for (int num = 1; num <= range; num++){ + sb.append(counter[num]).append("x ").append(num).append("\n"); + } + } + + thisEvent.getChannel().sendMessage(sb.toString()).queue(); + } + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Modules/Fold.java b/src/main/java/Modules/Fold.java new file mode 100644 index 0000000..5b18039 --- /dev/null +++ b/src/main/java/Modules/Fold.java @@ -0,0 +1,251 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Fold extends SuperModule{ + + private final Logger logger = LoggerFactory.getLogger(Fold.class); + public static final String COMMAND = "fold"; + + private static final int BYTE_LIMIT = 16 * 1024; + private static final int MAX_MESSAGE_LIMIT = 10; + + private static final String teamSummary = "https://apps.foldingathome.org/daily_team_summary.txt", + userSummary = "https://apps.foldingathome.org/daily_user_summary.txt"; + + private String teamFile = "/home/bots/MissingIdentifier/MissingIdent/team_summary.txt", + userFile = "/home/bots/MissingIdentifier/MissingIdent/user_summary.txt"; + + public Fold(GuildController guildController){ + super(COMMAND, guildController, null); + } + + @Override + public String getCommand() { + return Fold.COMMAND; + } + + @Override + public String getDescription() { + return "Get statistics for a team that partakes in https://foldingathome.org\n`fold -t TEAMNAME` teamname to be filtered\n`fold -u update` update statistics"; + } + + @Override + public void execute(GenericEvent genericEvent) { + if (!(genericEvent instanceof GuildMessageReceivedEvent)) return; + + GuildMessageReceivedEvent event = (GuildMessageReceivedEvent) genericEvent; + + if (!isCommand(event.getMessage())) + return; + + logger.debug("Fold command triggered"); + + //VARS + Pattern teamPattern, userPattern; + Message msg = event.getChannel().sendMessage("Got it!").complete(); + String teamInfo = null; + + // Update Locale Files if parameter "u" is given + if (getParameter(event.getMessage().getContentRaw(), "u") != null) + msg = update(event, msg); + + // Generate Pattern to look for decide if looking for ID or Name of Team fall back is null and will cause an error + if (getParameter(event.getMessage().getContentRaw(), "t") != null) { + String input = getParameter(event.getMessage().getContentRaw(), "t"); + logger.info("looking for team: " + input); + teamPattern = Pattern.compile("(?m)^[0-9]+\\t" + input + "\\t[0-9]+\\t[0-9]+$"); + } else if (getParameter(event.getMessage().getContentRaw(), "id") != null) { + String input = getParameter(event.getMessage().getContentRaw(), "id"); + logger.info("looking for team: " + input); + teamPattern = Pattern.compile("(?m)^" + input + "\\t[^\\t]*\\t[0-9]+\\t[0-9]+$"); + } else + return; // TODO error handling + + + //LOOK for Team + try (BufferedReader teamReader = Files.newBufferedReader(Paths.get(teamFile))) { + + teamInfo = teamReader.readLine(); + while (teamInfo != null) { + Matcher teamMatcher = teamPattern.matcher(teamInfo); + if (teamMatcher.find()) { + // Send quick info + msg = msg.editMessage(teamMatcher.group()).complete(); + break; + } + teamInfo = teamReader.readLine(); + } + } catch (IOException e) { + logger.error(e.toString()); + } + + if (teamInfo == null) { + msg.editMessage("No team with this Identifier found!").queue(); + return; + } + + // Look for users + try (BufferedReader userReader = Files.newBufferedReader(Paths.get(userFile))) { + + // Like skringbuilder only for embeded messages + EmbedBuilder eb = new EmbedBuilder(); + + // Add Team info + eb.setTitle(teamInfo.split("\t")[1] + " [ " + teamInfo.split("\t")[0] + " ]"); // Team Name + eb.setDescription("Work Units done:\t" + teamInfo.split("\t")[3] + "\n" + + "Total Score:\t\t" + teamInfo.split("\t")[2]); // WUs and Score + eb.setTimestamp(new DateTime().toDate().toInstant()); + + userPattern = Pattern.compile("(?m)^[0-9a-zA-Z_]+\\t[0-9]+\\t[0-9]+\\t" + teamInfo.split("\t")[0] + "$"); + String userInfo = userReader.readLine(); + + long userPosition = 0; + int messageCount = 0; + msg = msg.editMessage(teamInfo + "\n\nread 0 lines").complete(); + + while (userInfo != null) { + userPosition++; + Matcher userMatcher = userPattern.matcher(userInfo); + if (userMatcher.find()) { + eb.addField(userInfo.split("\t")[0], "Work Units:\t" + userInfo.split("\t")[2] + "\n" + + "Score:\t\t" + userInfo.split("\t")[1], true); + + //msg = msg.editMessage(teamInfo + "\n\nread " + userPosition + " lines").complete(); + // IF mesage is to long, rmeove last entry and split output + if (!eb.isValidLength()){ + eb.getFields().remove(eb.getFields().size()-1); + msg.getChannel().sendMessage(eb.build()).complete(); + + eb = new EmbedBuilder(); + messageCount++; + + if(messageCount > MAX_MESSAGE_LIMIT){ + msg.getChannel().sendMessage("To many entries! aborted to prevent spam!").queue(); + return; + } + + eb.addField(userInfo.split("\t")[0], "Work Units:\t" + userInfo.split("\t")[2] + "\n" + + "Score:\t\t" + userInfo.split("\t")[1], true); + + } + } + + if (userPosition % 250000 == 0) + msg = msg.editMessage(teamInfo + "\n\nread " + userPosition + " lines").complete(); + + userInfo = userReader.readLine(); + } + + //Send final result + msg.getChannel().sendMessage(eb.build()).complete(); + msg.delete().queue(); + } catch (IOException e) { + logger.error(e.toString()); + } + } + + private Message update(GuildMessageReceivedEvent event, Message msg) { + if(!checkForAdmin(event.getMember())) + { + // if the user that calls this function is not admin, here should be an interval check that interrupts if the files have recently been updated to mitigate abuse. + // admins should of course be able to call this any time. + // the date of the current files can be read from the first line of each file and needs to be parsed. + return msg; // if it's not done by an admin, just cancel out + } + + logger.debug("Get new Statistic from Server"); + + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + + // Activate the new trust manager + try { + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + logger.error(e.toString()); + } + + byte buffer[] = new byte[BYTE_LIMIT]; + int bytesRead; + + try( + BufferedOutputStream teamOutput = new BufferedOutputStream(new FileOutputStream(teamFile, false)); + BufferedInputStream teamInput = new BufferedInputStream(new URL(teamSummary).openStream()) + ) { + long i = 0; + while((bytesRead = teamInput.read(buffer, 0, BYTE_LIMIT)) != -1){ + teamOutput.write(buffer, 0, bytesRead); + + i+=bytesRead; + + if (i % 50000 <= 200) + msg = msg.editMessage("Updating Teamstats, processed " + i + " Bytes").complete(); + + } + + teamOutput.flush(); + } catch (IOException e) { + logger.error(e.toString()); + } + + try( + BufferedOutputStream userOutput = new BufferedOutputStream(new FileOutputStream(userFile, false)); + BufferedInputStream userInput = new BufferedInputStream(new URL(userSummary).openStream()) + ){ + long i = 0; + while((bytesRead = userInput.read(buffer, 0, BYTE_LIMIT)) != -1){ + userOutput.write(buffer, 0, bytesRead); + + i+=bytesRead; + + if (i % 50000 <= 200) + msg = msg.editMessage("Updating Userstats, processed " + i + " Bytes").complete(); + } + + userOutput.flush(); + } catch (IOException e) { + logger.error(e.toString()); + } + + return msg.editMessage("done!").complete(); + + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Modules/LoveCalc.java b/src/main/java/Modules/LoveCalc.java new file mode 100644 index 0000000..5bcbe47 --- /dev/null +++ b/src/main/java/Modules/LoveCalc.java @@ -0,0 +1,69 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; + + +public class LoveCalc extends SuperModule{ + + private final Logger logger = LoggerFactory.getLogger(LoveCalc.class); + public static final String command = "lovecalc"; + + /** + * Construcker of a Module + * + * @param guildController Guild where Module is used, each guild get its own Module + */ + public LoveCalc(GuildController guildController) { + super(command, guildController); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "Mention two users and Amour will tell you his probability to hit those two with his arrows"; + } + + @Override + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent){ + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(command + "triggered"); + + EmbedBuilder eb = new EmbedBuilder(); + + int love = (int)((thisEvent.getMessage().getMentionedUsers().get(0).getIdLong() + thisEvent.getMessage().getMentionedUsers().get(1).getIdLong()) % 100); + System.out.println("Do Lovecalc! love is: " + love); + + eb.setAuthor("Amour"); + eb.setColor(new Color((100-love)/100f,(love)/100f,0)); + eb.setTitle("chance that Amours arrows will hit " + thisEvent.getMessage().getMentionedUsers().get(0).getName() + + " and " + thisEvent.getMessage().getMentionedUsers().get(1).getName() + ":" ); + eb.setDescription(love + "%"); + + thisEvent.getChannel().sendMessage(eb.build()).queue(); + } + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Modules/Module.java b/src/main/java/Modules/Module.java new file mode 100644 index 0000000..fdcc126 --- /dev/null +++ b/src/main/java/Modules/Module.java @@ -0,0 +1,31 @@ +package Modules; + +import net.dv8tion.jda.api.events.GenericEvent; + +public interface Module { + + /** + * name of the command + * @return command + */ + String getCommand(); + + /** + * Text shown in the Help message + * @return Description + */ + String getDescription(); + + /** + * Recives Guild Updates + * @param genericEvent Guild Updates + */ + void execute(GenericEvent genericEvent); + + /** + * Returns the current settings of the module + * When no settings are needed return NULL + * @return current settings + */ + String showSettings(); +} diff --git a/src/main/java/Modules/OnlineHighlight.java b/src/main/java/Modules/OnlineHighlight.java new file mode 100644 index 0000000..e85e23f --- /dev/null +++ b/src/main/java/Modules/OnlineHighlight.java @@ -0,0 +1,186 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.events.user.UserActivityEndEvent; +import net.dv8tion.jda.api.events.user.UserActivityStartEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateActivityOrderEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class OnlineHighlight extends SuperModule { + + public static final String command = "OnlineHighlight"; + private Set watchGame; + private String watchRole; + + public OnlineHighlight(GuildController guildController, JSONObject config){ + + super(command, guildController, config); + //long welcomeChannel, String welcomeMessage + + if (!getConfig().containsKey("watchGame")){ + getConfig().put("watchGame", new JSONArray()); + safeConfig(getConfig()); + } + if (!getConfig().containsKey("watchRole")){ + getConfig().put("watchRole", ""); + safeConfig(getConfig()); + } + + //get welcome message + this.watchGame = new HashSet<>(); + for (Object o: (JSONArray)config.get("watchGame")){ + this.watchGame.add((String)o); + } + + this.watchRole = config.get("watchRole").toString(); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "Gives users who play a certain game a certain role\n" + + "`" + command + " addGame NAME` - to set game to look for\n" + + "`" + command + " setRole @ROLE` - to set role which users playing teh game will get"; + } + + @Override + public void execute(GenericEvent event) { + + if(event instanceof GuildMessageReceivedEvent){ + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (checkForAdmin(thisEvent.getGuild().getMember(thisEvent.getAuthor()))) + return; + + if(checkForCommand(thisEvent.getMessage().getContentRaw(), "showGames")){ + + Set act = new HashSet<>(); + for (Member member : thisEvent.getGuild().getMembers()){ + act.add(member.getActivities().get(0).getName()); + } + + StringBuilder sb = new StringBuilder(); + sb.append("Currently played games are:\n"); + for (String s : act) + sb.append("`").append(s).append("`, "); + + thisEvent.getChannel().sendMessage(sb.toString()).queue(); + + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "addGame")){ + JSONArray oldConf = (JSONArray) getConfig().remove("watchGame"); + + String newGame = thisEvent.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + command + " addGame )","").toLowerCase(); + + if (watchGame.contains(newGame)){ + thisEvent.getChannel().sendMessage("ERROR: Game already on the list! use `delGame` to remove it.").queue(); + return; + } + + oldConf.add(newGame); + getConfig().put("watchGame", oldConf); + safeConfig(); + + watchGame.add(newGame); + + StringBuilder sb = new StringBuilder(); + sb.append("Watched Games are: "); + for (String s : watchGame) + sb.append("`").append(s).append("`, "); + + sb.replace(sb.length()-2,sb.length(), ""); + + thisEvent.getChannel().sendMessage(sb.toString()).queue(); + + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "delGame")){ + JSONArray oldConf = (JSONArray) getConfig().remove("watchGame"); + + String delGame = thisEvent.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + command + " delGame )","").toLowerCase(); + + if (!watchGame.contains(delGame)){ + thisEvent.getChannel().sendMessage("ERROR: Game is not on the list!").queue(); + return; + } + + oldConf.remove(delGame); + getConfig().put("watchGame", oldConf); + safeConfig(); + + watchGame.remove(delGame); + + thisEvent.getChannel().sendMessage("Game `" + delGame + "` got removed from list.").queue(); + + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "setRole")){ + + if (thisEvent.getMessage().getMentionedRoles().size() != 1){ + thisEvent.getChannel().sendMessage("No Role Mentioned, abort").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + getConfig().remove("watchRole"); + getConfig().put("watchRole", thisEvent.getMessage().getMentionedRoles().get(0).getIdLong()); + + safeConfig(); + + thisEvent.getChannel().sendMessage("Set watchRole to: `" + thisEvent.getGuild().getRoleById(getConfig().get("watchRole").toString()).getName() + "`").queue(); + } + } + + if (event instanceof UserActivityStartEvent){ + UserActivityStartEvent thisEvent = (UserActivityStartEvent) event; + + if(watchGame.contains(thisEvent.getNewActivity().getName().toLowerCase())){ + thisEvent.getGuild().addRoleToMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(watchRole)).queue(); + } + } else if (event instanceof UserActivityEndEvent){ + UserActivityEndEvent thisEvent = (UserActivityEndEvent ) event; + + if(watchGame.contains(thisEvent.getOldActivity().getName().toLowerCase())) { + thisEvent.getGuild().removeRoleFromMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(watchRole)).queue(); + } + } + + if (event instanceof UserUpdateActivityOrderEvent){ + UserUpdateActivityOrderEvent thisEvent = (UserUpdateActivityOrderEvent ) event; + if (watchGame.contains(thisEvent.getNewValue().get(0).getName().toLowerCase())){ + //TODO + thisEvent.getGuild().addRoleToMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(watchRole)).queue(); + } else { + if (thisEvent.getMember().getRoles().contains(thisEvent.getGuild().getRoleById(watchRole))) + thisEvent.getGuild().removeRoleFromMember(thisEvent.getMember(), thisEvent.getGuild().getRoleById(watchRole)).queue(); + } + } + + } + + @Override + public String showSettings() { + StringBuilder sb = new StringBuilder(); + sb.append("watchGame: "); + + for (String s: watchGame) + sb.append("`").append(s).append("`, "); + + sb.replace(sb.length()-2,sb.length(), ""); + + sb.append("\nwatchRole: ").append(getGuildController().getJda() + .getGuildById(getGuildController().getGUILD_ID()) + .getRoleById(watchRole).getName()); + + return sb.toString(); + } +} diff --git a/src/main/java/Modules/Purge.java b/src/main/java/Modules/Purge.java new file mode 100644 index 0000000..8a63b0e --- /dev/null +++ b/src/main/java/Modules/Purge.java @@ -0,0 +1,98 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import java.util.concurrent.TimeUnit; + +public class Purge extends SuperModule{ + + private final Logger logger = LoggerFactory.getLogger(Purge.class); + public static final String COMMAND = "purge"; + + public Purge(GuildController guildController){ + super(COMMAND, guildController, null); + } + + @Override + public String getCommand() { + return Purge.COMMAND; + } + + @Override + public String getDescription() { + return "Deletes Messages.\n`-n NUMBER` number of messages to delete\n`@USER` delete messages from user only."; + } + + @Override + public void execute(GenericEvent genericEvent) { + + GuildMessageReceivedEvent event = null; + List messageIds = null; + long counter = -1, limiter = -1; + messageIds = new ArrayList(); + + // if this is a GuildMessageReceivedEvent, cast it, else return + if (!(genericEvent instanceof GuildMessageReceivedEvent)) return; + + event = (GuildMessageReceivedEvent) genericEvent; + + if (!isCommand(event.getMessage())) + return; + + logger.debug(COMMAND + "triggered"); + + // if the author of the message has the mod privileges or is the owner continue, else return + if (!checkForAdmin(event.getMember())){ + + event.getChannel().sendMessage("I am Sorry, you are not allowed to do that!\nMay ask " + + event.getGuild().getRoleById(getGuildController().getMOD_ROLE()).getAsMention() + " to do that.").queue( + m -> m.delete().queueAfter(30, TimeUnit.SECONDS) + ); + + event.getMessage().delete().queueAfter(30, TimeUnit.SECONDS); + + return; + } + + // if the message contains "purge[whitespace]-n[whitespace]messageCount", parse messageCount and delete that many messages + if (getParameter(event.getMessage().getContentRaw(), "n") != null) { + limiter = Integer.parseInt(getParameter(event.getMessage().getContentRaw(),"n")); + } else { + limiter = 10; + } + + //if there was no messageCount to be parsed, limiter will run from -1 towards negative and never reach 0 (ignoring overflow), full purge + for (Message msg : event.getChannel().getIterableHistory()) { + + if (!msg.isPinned() && + (event.getMessage().getMentionedMembers().size() != 1 + || msg.getAuthor().getIdLong() == event.getMessage().getMentionedMembers().get(0).getIdLong())) { + messageIds.add(msg.getId()); + counter++; + limiter--; + } + if (limiter < 0) break; + } + + // purge all collected messages + event.getChannel().purgeMessagesById(messageIds); + + event.getChannel().sendMessage(counter + " messages purged.").queue(message -> message.delete().queueAfter(1, TimeUnit.MINUTES)); + + logger.debug(counter + " messages purged."); + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Modules/Quote.java b/src/main/java/Modules/Quote.java new file mode 100644 index 0000000..81b9e2d --- /dev/null +++ b/src/main/java/Modules/Quote.java @@ -0,0 +1,187 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import IO.JSON; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; + +public class Quote extends SuperModule{ + + private final Logger logger = LoggerFactory.getLogger(Quote.class); + public static final String command = "quote"; + static final String QUOTE_LOCATION = "Quotes.json"; + + public Quote(GuildController guildController){ + super(command, guildController); + + if(JSON.loadJson(QUOTE_LOCATION) == null){ + JSON.saveJson(new JSONArray(), QUOTE_LOCATION); + } + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "`quote` shows random quote\n`quote id #NUMBER` show specific quote\n`quote new QUOTE - AUTHOR` adds new quote to the system"; + } + + @Override + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent) { + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug(command + "triggered"); + + /////////////////// + // ADD NEW QUOTE + /////////////////// + if (thisEvent.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + command + " (new|add) .*)")) { + logger.debug("safe new Quote"); + + // Prep new Quote Object + JSONObject newQuote = new JSONObject(); + newQuote.put("text", thisEvent.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + command + " (new|add) )", "") + .replaceAll("(?is:-.*$)","")); + newQuote.put("date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + if (thisEvent.getMessage().getContentRaw().contains("-")) + newQuote.put("author", thisEvent.getMessage().getContentRaw().replaceAll("(?is:[^-]*- )", "")); + + + JSONArray arr = JSON.loadJson(QUOTE_LOCATION); + boolean exists = false; + + // go through all Guilds + for (Object o: arr){ + + //Filter for the right guild + JSONObject guilds = (JSONObject) o; + if (guilds.get("guildID").equals(getGuildController().getGUILD_ID())){ + + arr.remove(o); // Remove old object + JSONArray guildQuotes = (JSONArray) guilds.get("quotes"); // get old Quotes + + guildQuotes.add(newQuote); // add new Quote + + JSONObject editedGuild = new JSONObject(); // safe guild + editedGuild.put("guildID", getGuildController().getGUILD_ID()); + editedGuild.put("quotes", guildQuotes); + arr.add(editedGuild); + + exists = true; // set flag + break; + } + } + + if (!exists){ // if flag not set create new Guild + JSONObject newGuild = new JSONObject(); + newGuild.put("guildID", getGuildController().getGUILD_ID()); + + JSONArray newQuotes = new JSONArray(); + newQuotes.add(newQuote); + + newGuild.put("quotes", newQuotes); + arr.add(newGuild); + } + + // Safe data + JSON.saveJson(arr, QUOTE_LOCATION); + + + thisEvent.getMessage().delete().queue(); + + /////////////////// + // PICK QUOTE BY ID + /////////////////// + } else if (thisEvent.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + command + " id #[0-9]+.*)")){ + logger.debug("pick Quote by ID"); + + //STUB + + /////////////////// + // RandomPick + /////////////////// + } else { + logger.debug("random quote pick"); + + JSONArray arr = JSON.loadJson(QUOTE_LOCATION); + + for (Object o : arr){ + JSONObject guild = (JSONObject) o; + + if (guild.get("guildID").equals(getGuildController().getGUILD_ID())){ + + JSONArray quotes = (JSONArray) guild.get("quotes"); + + JSONObject quote = null; + int i = 0; + // Get Random Quote Object + do { + quote = (JSONObject) quotes.get(new Random().nextInt(quotes.size())); + i++; + + if (i > quotes.size()) + return; + } while (quote == null); + + // Build message + EmbedBuilder eb = new EmbedBuilder(); + + // get text + eb.setDescription(quote.get("text").toString()); + + // get Date + try { + eb.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(quote.get("date").toString()).toInstant()); + } catch (ParseException e){ + logger.error(e.toString()); + } + + //get Author if exists + if (quote.containsKey("author")){ + eb.setAuthor(quote.get("author").toString()); + } + + thisEvent.getChannel().sendMessage(eb.build()).queue(); + break; + } + } + } + //Delete command + thisEvent.getMessage().delete().queue(); + } + } + + @Override + public String showSettings() { + JSONArray arr = JSON.loadJson(QUOTE_LOCATION); + for (Object o : arr) { + JSONObject guild = (JSONObject) o; + + if (guild.get("guildID").equals(getGuildController().getGUILD_ID())) { + return "NUMBER OF QUOTES: `" + ((JSONArray) guild.get("quotes")).size() + "`"; + } + } + return "NUMBER OF QUOTES: `0`"; + } +} diff --git a/src/main/java/Modules/RandomResponde.java b/src/main/java/Modules/RandomResponde.java new file mode 100644 index 0000000..3e47e31 --- /dev/null +++ b/src/main/java/Modules/RandomResponde.java @@ -0,0 +1,158 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RandomResponde extends SuperModule{ + + public static final String command = "RandomResponse"; + + public RandomResponde(GuildController guildController, JSONObject config) { + super(command, guildController, config); + + if (!config.containsKey("triggers")){ + getConfig().put("triggers", new JSONArray()); + safeConfig(getConfig()); + } + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "response to predefined keywords. git as example\n" + + "`RandomResponse add -t TRIGGER -r RESPONSE [-p FILTERPATTERN]` if -p is set trigger will replace $pattern with REGEX filtered trigger message. Good example for such a REGEX may be: `((?<=(?is:TRIGGER)) [^ ]+)` (Filters next word to trigger)\n" + + "`RandomResponse remove TRIGGER` remove a trigger"; + } + + @Override + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent){ + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent)event; + + if (isCommand(thisEvent.getMessage())){ + // add new trigger + if (checkForCommand(thisEvent.getMessage().getContentRaw(), "add")){ + + JSONArray triggers = (JSONArray) getConfig().get("triggers"); + + // Check for obligatory parameter: + if(getParameter(thisEvent.getMessage().getContentRaw(), "t").length() < 1){ + thisEvent.getChannel().sendMessage("You have to mention a trigger! use `-t TRIGGER`").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + thisEvent.getMessage().delete().queueAfter(1, TimeUnit.MINUTES); + return; + } + if (getParameter(thisEvent.getMessage().getContentRaw(), "r").length() < 1){ + thisEvent.getChannel().sendMessage("You have to mention a response! use `-r RESPONSE`").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + thisEvent.getMessage().delete().queueAfter(1, TimeUnit.MINUTES); + return; + } + + // Check if already exists + for (Object o : triggers){ + if (((JSONObject)o).get("trigger").toString().equalsIgnoreCase( + getParameter(thisEvent.getMessage().getContentRaw(), "t") + )){ + thisEvent.getChannel().sendMessage("Trigger already exists! aborted").queue(msg -> msg.delete().queueAfter(1, TimeUnit.MINUTES)); + thisEvent.getMessage().delete().queueAfter(1, TimeUnit.MINUTES); + return; + } + } + + // new Object to add + JSONObject newTrigger = new JSONObject(); + + // add triiger / response + newTrigger.put("trigger", getParameter(thisEvent.getMessage().getContentRaw(), "t")); + newTrigger.put("response", getParameter(thisEvent.getMessage().getContentRaw(), "r")); + + // may add replacement and pattern + if (getParameter(thisEvent.getMessage().getContentRaw(), "p").length() > 0){ + // p param is given check if "$pattern" is given + if (newTrigger.get("response").toString().contains("$pattern")){ // Has valid pattern + newTrigger.put("pattern", getParameter(thisEvent.getMessage().getContentRaw(), "p")); + } else { // has no valid pattern + thisEvent.getChannel().sendMessage("You did not mentioned `$pattern` to apply the pattern").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + thisEvent.getMessage().delete().queueAfter(1, TimeUnit.MINUTES); + } + + } + + // add new Object and safe it + triggers.add(newTrigger); + getConfig().replace("triggers", triggers); + safeConfig(); + + thisEvent.getChannel().sendMessage("Added trigger!").queue(); + + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "remove")){ + JSONArray triggers = (JSONArray) getConfig().get("triggers"); + boolean deleted = false; + + for (Object ob : triggers){ + if(((JSONObject) ob).get("trigger").toString().equals( + thisEvent.getMessage().getContentRaw().replaceFirst( + "(?is:" + getGuildController().getPREFIX() + command + " " + "remove )", ""))){ + triggers.remove(ob); + deleted = true; + break; + } + } + + if (deleted){ + // safe it + getConfig().replace("triggers", triggers); + safeConfig(getConfig()); + + thisEvent.getChannel().sendMessage("deleted Trigger!").queue(); + } else { + // if noth ing got deletet entry does not exist + thisEvent.getChannel().sendMessage("no such Trigger! aborted action.").queue(); + } + } + + } else { + // go through all triggers and may responde + for (Object o : (JSONArray)getConfig().get("triggers")){ + JSONObject trigger = (JSONObject) o; + + if (thisEvent.getMessage().getContentRaw().matches("(?is:.*" + trigger.get("trigger").toString() + ".*)")){ + + String respnse = trigger.get("response").toString(); + + // get filter + if(trigger.containsKey("pattern")) { + Matcher m = Pattern.compile(trigger.get("pattern").toString()).matcher(thisEvent.getMessage().getContentRaw()); + + if(m.find()) + respnse = respnse.replaceAll("\\$pattern", m.group(0)); + else + respnse = respnse.replaceAll("\\$pattern", "NULL"); + } + + thisEvent.getChannel().sendMessage(respnse).queue(msg -> msg.delete().queueAfter(1, TimeUnit.MINUTES)); + break; + } + } + } + } + } + + @Override + public String showSettings() { + return "NUMBER OF TRIGGERS: `" + ((JSONArray) getConfig().get("triggers")).size() + "`"; + } +} diff --git a/src/main/java/Modules/SecretChannel.java b/src/main/java/Modules/SecretChannel.java new file mode 100644 index 0000000..b5d013a --- /dev/null +++ b/src/main/java/Modules/SecretChannel.java @@ -0,0 +1,232 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class SecretChannel extends SuperModule { + + public static final String COMMAND = "SecretChannel"; + + private Map userInChannel; + + private Long hiddenChannel; + private int activeTime; + private boolean pingUser; + private Set trigger; + + public SecretChannel(GuildController guildController, JSONObject config){ + super(COMMAND, guildController, config); + + if (!config.containsKey("trigger")){ + config.put("trigger", new JSONArray()); + safeConfig(getConfig()); + } + + if (!config.containsKey("hiddenChannel")){ + config.put("hiddenChannel", "123"); + safeConfig(getConfig()); + } + + if (!config.containsKey("pingUser")){ + config.put("pingUser", "false"); + safeConfig(getConfig()); + } + + if (!config.containsKey("activeTime")){ + config.put("activeTime", "30"); + safeConfig(getConfig()); + } + + trigger = new HashSet<>(); + for ( Object o : (JSONArray)config.get("trigger")){ + trigger.add(o.toString()); + } + + hiddenChannel = Long.parseLong(getConfig().get("hiddenChannel").toString()); + + activeTime = Integer.parseInt(getConfig().get("activeTime").toString()); + + pingUser = Boolean.parseBoolean(getConfig().get("pingUser").toString()); + + + } + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public String getDescription() { + return "Add user (Temporarily) to a hidden channel if the user mentions a trigger\n" + + "`addTrigger WORD` add new Trigger\n" + + "`removeTrigger WORD` remove existing Trigger\n" + + "`setChannel #CHANNEL` set channel to be shown\n" + + "`setTime NUMBER` set time channel is shown in seconds\n" + + "`togglePing` set if user gets a ping"; + } + + @Override + public void execute(GenericEvent genericEvent) { + + if (genericEvent instanceof GuildMessageReceivedEvent){ + GuildMessageReceivedEvent event = (GuildMessageReceivedEvent)genericEvent; + + if (checkForAdmin(event.getGuild().getMember(event.getAuthor()))) { + if (checkForCommand(event.getMessage().getContentRaw(), "addTrigger")) { + String newTrigger = event.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + COMMAND + " addTrigger )", ""); + + if (trigger.size() == 0) { + trigger.add(newTrigger); + + JSONArray arr = new JSONArray(); + arr.add(newTrigger); + getConfig().put("trigger", arr); + + + } else { + + if (trigger.contains(newTrigger)) { + event.getChannel().sendMessage("Error: Trigger already exists!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + trigger.add(newTrigger); + + JSONArray arr = ((JSONArray) getConfig().get("trigger")); + arr.add(newTrigger); + getConfig().remove("trigger"); + getConfig().put("trigger", arr); + + } + safeConfig(); + + event.getChannel().sendMessage("Added trigger `" + newTrigger + "`").queue(); + + } else if (checkForCommand(event.getMessage().getContentRaw(), "removeTrigger")) { + String delTrigger = event.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + COMMAND + " removeTrigger )", ""); + + if (!trigger.contains(delTrigger)) { + event.getChannel().sendMessage("Error: Trigger does not exists!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + trigger.remove(delTrigger); + + ((JSONArray) getConfig().remove("trigger")).add(delTrigger); + + safeConfig(); + + event.getChannel().sendMessage("Removed trigger `" + delTrigger + "`").queue(); + } else if (checkForCommand(event.getMessage().getContentRaw(), "setChannel")) { + + if (event.getMessage().getMentionedChannels().size() != 1) { + event.getChannel().sendMessage("Error: Please mention a Textchannel!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + hiddenChannel = event.getMessage().getMentionedChannels().get(0).getIdLong(); + + getConfig().remove("hiddenChannel"); + getConfig().put("hiddenChannel", hiddenChannel); + + safeConfig(); + + event.getChannel().sendMessage("Set Hiddenchannel to: `" + hiddenChannel + "` (" + + event.getMessage().getMentionedChannels().get(0).getAsMention() + ")").queue(); + + } else if (checkForCommand(event.getMessage().getContentRaw(), "setTime")) { + + if (!event.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + COMMAND + " setTime " + "[0-9]+)")) { + event.getChannel().sendMessage("Error: PLease enter a valid number!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + return; + } + + int newTime = Integer.parseInt(event.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + COMMAND + " setTime " + ")", "")); + + activeTime = newTime; + + getConfig().remove("activeTime"); + getConfig().put("activeTime", newTime); + + safeConfig(); + + event.getChannel().sendMessage("Set activeTime to: " + newTime).queue(); + + } else if (checkForCommand(event.getMessage().getContentRaw(), "togglePing")) { + + pingUser = !pingUser; + + getConfig().remove("pingUser"); + getConfig().put("pingUser", pingUser); + + safeConfig(); + + event.getChannel().sendMessage("Toggled pingUser to: " + pingUser).queue(); + + } + } + + if (trigger.size() > 0) { + StringBuilder sb = new StringBuilder(); + + for (String s : trigger) + sb.append("|").append(s); + + sb.replace(0, 1, ""); + + if (event.getMessage().getContentRaw().matches("(?is:.*(" + sb.toString() + ").*)")) { + + event.getGuild().getTextChannelById(hiddenChannel).upsertPermissionOverride(event.getMember()).complete() + .getManager().setAllow( + Permission.MESSAGE_READ, + Permission.VIEW_CHANNEL + ).queue(); + + if (pingUser) { + event.getGuild().getTextChannelById(hiddenChannel) + .sendMessage(event.getAuthor().getAsMention()).queue( + m -> m.delete().queueAfter(activeTime > 0 ? activeTime : 60, TimeUnit.SECONDS)); + } + + if (activeTime > 0) { + new Timer().schedule(new TimerTask() { + @Override + public void run() { + event.getGuild().getTextChannelById(hiddenChannel).getPermissionOverride(event.getMember()).delete().queue(); + } + }, TimeUnit.MILLISECONDS.convert(activeTime, TimeUnit.SECONDS)); + } + } + } + } + + } + + @Override + public String showSettings() { + + StringBuilder sb = new StringBuilder(); + + for (String s : trigger) + sb.append("|").append("`").append(s).append("`"); + + sb.replace(0,1, ""); + + return "hidden channel: `" + hiddenChannel + "` (" + getGuildController().getJda().getGuildById(getGuildController().getGUILD_ID()).getTextChannelById(hiddenChannel).getAsMention() + ")\n" + + "activeTime: `" + activeTime + "`\n" + + "ping User: `" + pingUser + "` \n" + + "Trigger: " + sb.toString(); + } +} diff --git a/src/main/java/Modules/Shuffle.java b/src/main/java/Modules/Shuffle.java new file mode 100644 index 0000000..77545eb --- /dev/null +++ b/src/main/java/Modules/Shuffle.java @@ -0,0 +1,96 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; +import java.util.Random; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; + +/** + * @author https://www.Hiajen.de + */ +public class Shuffle extends SuperModule{ + + public static final String command = "shufflerole"; + private static final String desc = "changes color of shufflerole randomly\n" + + "`shufflerole setRole @ROLE` Set role to shuffle"; + private final Logger logger = LoggerFactory.getLogger(Shuffle.class); + + private long role; + + public Shuffle(GuildController guildController, JSONObject config){ + + super(command, guildController, config); + + if (!config.containsKey("role")){ + getConfig().put("role", "123"); + safeConfig(getConfig()); + } + + // JDA api, long role, long guild + this.role = Long.parseLong(getConfig().get("role").toString()); + + shuffleColor(); + } + + private void shuffleColor(){ + TimerTask repeatedTask = new TimerTask() { + public void run() { + //logger.debug("shuffle role color"); + + Random r = new Random(); + getGuildController().getJda().getGuildById(getGuildController().getGUILD_ID()).getRoleById(role) + .getManager().setColor(new Color(r.nextFloat(),r.nextFloat(),r.nextFloat())).queue(); + } + }; + Timer timer = new Timer(); + + timer.schedule(repeatedTask, TimeUnit.SECONDS.toMillis(10), TimeUnit.SECONDS.toMillis(120)); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return desc; + } + + @Override + public void execute(GenericEvent event) { + if (event instanceof GuildMessageReceivedEvent){ + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + if (checkForCommand(thisEvent.getMessage().getContentRaw(), "setRole") && checkForAdmin(thisEvent.getMember())){ + if (thisEvent.getMessage().getMentionedRoles().size() == 1){ + getConfig().replace("role", thisEvent.getMessage().getMentionedRoles().get(0).getIdLong()); + + role = thisEvent.getMessage().getMentionedRoles().get(0).getIdLong(); + thisEvent.getChannel().sendMessage("okay changed Role!").queue(); + + safeConfig(getConfig()); + } else { + thisEvent.getChannel().sendMessage("Please mention one Role!").queue(m -> m.delete().queueAfter(1, TimeUnit.MINUTES)); + } + } + } + } + + @Override + public String showSettings() { + return "ROLE: `" + ((getGuildController().getJda().getRoleById(role) == null) ? "none" : getGuildController().getJda().getRoleById(role).getName()) + "`"; + } +} diff --git a/src/main/java/Modules/Stats.java b/src/main/java/Modules/Stats.java new file mode 100644 index 0000000..808aaec --- /dev/null +++ b/src/main/java/Modules/Stats.java @@ -0,0 +1,54 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONObject; + +public class Stats extends SuperModule { + + public static final String COMMAND = "stats"; + + public Stats(GuildController guildController, JSONObject config) { + super(COMMAND, guildController, config); + + + } + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public String getDescription() { + return "Shows some statistics about this Guild"; + } + + @Override + public void execute(GenericEvent event) { + + if (event instanceof GuildMessageReceivedEvent){ + + GuildMessageReceivedEvent input = (GuildMessageReceivedEvent) event; + + if (isCommand(input.getMessage())){ + + EmbedBuilder eb = new EmbedBuilder() + .setTitle("Current stats") + .addField("Usercount", input.getGuild().getMemberCount()+"", true) + .addField("Rolecount", input.getGuild().getRoles().size()+"", true) + .setImage(input.getGuild().getIconUrl()); + + input.getChannel().sendMessage(eb.build()).queue(); + } + } + } + + @Override + public String showSettings() { + return null; + } +} diff --git a/src/main/java/Modules/VoiceLobby.java b/src/main/java/Modules/VoiceLobby.java new file mode 100644 index 0000000..0c234dc --- /dev/null +++ b/src/main/java/Modules/VoiceLobby.java @@ -0,0 +1,228 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.entities.VoiceChannel; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.GenericGuildEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +import java.util.HashSet; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VoiceLobby extends SuperModule { + + public static final String command = "lobby"; + private static final String description = "Create temporary channels.\n" + + "`lobby create -n NAME -l USERLIMIT` creates new temporary channel, without parameter default values will be used.\n" + + "`lobby limit USERLIMIT` set new user limit.\n" + + "`lobby name NAME` set new channel name.\n" + + "`lobby setLobbyChannel CATEGORY_ID` to set Category where lobbies will spawn. \n" + + "`lobby setLaunchpad VOICE_CHANNEL_ID` to set a Launchpad channel (user who join this channel will get moved in a new temporary channel)"; + + private long groupCategory; + private long launchpadChannel; + private HashSet tmpChannel = new HashSet<>(); + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + public VoiceLobby(GuildController guildController, JSONObject config){ + + super(command, guildController, config); + + if (!getConfig().containsKey("groupCategory")){ + getConfig().put("groupCategory", "123"); + safeConfig(getConfig()); + } + if(!getConfig().containsKey("LaunchpadChannel")){ + getConfig().put("LaunchpadChannel", "123"); + safeConfig(getConfig()); + } + + //long groupCategory + this.groupCategory = Long.parseLong(getConfig().get("groupCategory").toString()); + this.launchpadChannel = Long.parseLong(getConfig().get("LaunchpadChannel").toString()); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public void execute(GenericEvent genericEvent) { + + if (!(genericEvent instanceof GenericGuildEvent)) + return; + + GenericGuildEvent event = (GenericGuildEvent) genericEvent; + + if (event instanceof GuildMessageReceivedEvent) { + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + logger.debug("Lobby command triggered"); + + //////////////////////// + // CREATE TMP CHANNEL + //////////////////////// + if (checkForCommand(thisEvent.getMessage().getContentRaw(), "create")) { + //check if user is in Voice Channel + if (thisEvent.getMember().getVoiceState().inVoiceChannel()) { + //Pattern + Matcher name = Pattern.compile("(?is:-n [^ ]+)").matcher(thisEvent.getMessage().getContentRaw()); + Matcher limit = Pattern.compile("(?is:-l [0-9]+)").matcher(thisEvent.getMessage().getContentRaw()); + //TODO + Matcher privateChannel = Pattern.compile("(?is:-p)").matcher(thisEvent.getMessage().getContentRaw()); + + //Create Voice channel + VoiceChannel newChannel = event.getGuild().createVoiceChannel(name.find() ? name.group(0).replace("-n ", "").replaceAll(" $", "") : "TEMP") + .setParent(event.getGuild().getCategoryById(groupCategory)) + .setUserlimit(limit.find() ? Integer.parseInt(limit.group(0).replace("-l ", "").replaceAll(" $", "")) : 3).complete(); + + // move User + event.getGuild().moveVoiceMember(((GuildMessageReceivedEvent) event).getMember(), newChannel).queue(); + tmpChannel.add(newChannel.getIdLong()); + + } else { + thisEvent.getChannel().sendMessage("Please Join a Voice Channel first!").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + } + //////////////////////// + // Set Limit + //////////////////////// + } else if (thisEvent.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + command + " limit [0-9]+)")) { + + //check if user is in Voice Channel and a temp channel + if (thisEvent.getMember().getVoiceState().inVoiceChannel() && thisEvent.getMember().getVoiceState().getChannel().getParent().getIdLong() == groupCategory) { + + //Set new Limit + thisEvent.getMember().getVoiceState().getChannel().getManager().setUserLimit(Integer.parseInt( + thisEvent.getMessage().getContentRaw().replaceAll(".* limit ", "")) + ).queue(); + + thisEvent.getChannel().sendMessage( + "Set limit to " + thisEvent.getMessage().getContentRaw().replaceAll(".* limit ", "")) + .queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + + } else { + thisEvent.getChannel().sendMessage("You are not in a lobby channel!").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + } + //////////////////////// + // Set name + //////////////////////// + } else if (thisEvent.getMessage().getContentRaw().matches("(?is:" + getGuildController().getPREFIX() + command + " name [^ ]+)")) { + + //check if user is in Voice Channel and a temp channel + if (thisEvent.getMember().getVoiceState().inVoiceChannel() && thisEvent.getMember().getVoiceState().getChannel().getParent().getIdLong() == groupCategory) { + + //Set new Limit + thisEvent.getMember().getVoiceState().getChannel().getManager().setName( + thisEvent.getMessage().getContentRaw().replaceAll(".* name ", "") + ).queue(); + + thisEvent.getChannel().sendMessage( + "Set name to " + thisEvent.getMessage().getContentRaw().replaceAll(".* name ", "")) + .queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + + } else { + thisEvent.getChannel().sendMessage("You are not in a lobby channel!").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + } + //////////////////////// + // Set Lobby Category + //////////////////////// + } else if (checkForAdmin(thisEvent.getMember()) && checkForCommand(thisEvent.getMessage().getContentRaw(), "setLobbyChannel")) { + + Matcher m = Pattern.compile("(?is:[0-9]+)").matcher(thisEvent.getMessage().getContentRaw()); + if (m.find() && thisEvent.getGuild().getCategoryById(m.group(0)) != null) { + getConfig().replace("groupCategory", m.group(0) + ""); + + thisEvent.getChannel().sendMessage("Set groupCategory to: " + m.group(0)).queue(); + safeConfig(getConfig()); + } else { + thisEvent.getChannel().sendMessage("no valid Category!").queue(); + } + + thisEvent.getMessage().delete().queue(); + //////////////////////// + // Set Launchpad + //////////////////////// + } else if (checkForAdmin(thisEvent.getMember()) && checkForCommand(thisEvent.getMessage().getContentRaw(), "setLaunchpad")) { + + if (thisEvent.getMessage().getContentRaw().matches("(?is:.*[0-9]+.*)")) { // check if a Voice channel could be given + Matcher m = Pattern.compile("(?is:[0-9]+)").matcher(thisEvent.getMessage().getContentRaw()); + if (m.find() && thisEvent.getGuild().getVoiceChannelById(m.group(0)) != null) { + getConfig().put("LaunchpadChannel", m.group(0)); + safeConfig(getConfig()); + + this.launchpadChannel = Long.parseLong(getConfig().get("LaunchpadChannel").toString()); + thisEvent.getChannel().sendMessage("Launchpad set to `" + m.group(0) + "` (" + thisEvent.getGuild().getVoiceChannelById(m.group(0)).getName() + ")").queue(); + return; + } + } + + thisEvent.getChannel().sendMessage("Something went wrong, are you sure that you mentioned an VoicechannelID?").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES)); + + } + } else if (event instanceof GuildVoiceUpdateEvent) { + GuildVoiceUpdateEvent thisEvent = (GuildVoiceUpdateEvent) event; + + //check if user left a temp channel + if ((thisEvent.getChannelLeft() != null && thisEvent.getChannelLeft().getParent().getIdLong() == groupCategory)) { + //check if channel is now empty + if (thisEvent.getChannelLeft().getMembers().size() < 1 && tmpChannel.contains(thisEvent.getChannelLeft().getIdLong())) { + + logger.debug("may remove channel: " + thisEvent.getChannelLeft().getId()); + //wait for 30 seconds and check again + //then delete channel if still empty + new Timer().schedule(new TimerTask() { + @Override + public void run() { + if (thisEvent.getChannelLeft().getMembers().size() < 1) { + + logger.debug("remove channel: " + thisEvent.getChannelLeft().getId()); + thisEvent.getChannelLeft().delete().queue(); + tmpChannel.remove(thisEvent.getChannelLeft().getIdLong()); + } else { + logger.debug("dont remove channel: " + thisEvent.getChannelLeft().getId()); + } + } + }, TimeUnit.SECONDS.convert(30, TimeUnit.MILLISECONDS)); + } + } + + if ((thisEvent.getChannelJoined() != null && thisEvent.getChannelJoined().getIdLong() == launchpadChannel)) { + logger.debug("Triggered Launchpad"); + + //Create Voice channel + VoiceChannel newChannel = event.getGuild().createVoiceChannel("Temp-Lobby", event.getGuild().getCategoryById(groupCategory)) + .complete(); + + // move User + event.getGuild().moveVoiceMember(thisEvent.getEntity(), newChannel).queue(); + tmpChannel.add(newChannel.getIdLong()); + } + } + } + + @Override + public String showSettings() { + return "LOBBYCHANNEL: `" + ((getGuildController().getJda().getCategoryById(groupCategory) == null) ? "none" : getGuildController().getJda().getCategoryById(groupCategory).getName()) + "`" + + "LaunchpadChannel: `"+ launchpadChannel + "`"; + } +} diff --git a/src/main/java/Modules/Welcome.java b/src/main/java/Modules/Welcome.java new file mode 100644 index 0000000..1824f2a --- /dev/null +++ b/src/main/java/Modules/Welcome.java @@ -0,0 +1,111 @@ +package Modules; + +import Controll.GuildController; +import Controll.SuperModule; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Welcome extends SuperModule { + public static final String command = "welcome"; + + private final Logger logger = LoggerFactory.getLogger(Welcome.class); + + private String welcomeMessage; + private long welcomeChannel; + + public Welcome(GuildController guildController, JSONObject config){ + + super(command, guildController, config); + //long welcomeChannel, String welcomeMessage + + if (!getConfig().containsKey("welcomeMessage")){ + getConfig().put("welcomeMessage", "Hi $USER"); + safeConfig(getConfig()); + } + if (!getConfig().containsKey("welcomeChannel")){ + getConfig().put("welcomeChannel", "123"); + safeConfig(getConfig()); + } + + //get welcome message + this.welcomeMessage = config.get("welcomeMessage").toString(); + this.welcomeChannel = Long.parseLong(config.get("welcomeChannel").toString()); + } + + @Override + public String getCommand() { + return command; + } + + @Override + public String getDescription() { + return "Welcomes new Members\n" + + "`welcome SetWelcomeMessage MESSAGE` set Welcome message use `$USER` to mention the new user\n" + + "`welcome SetWelcomeChannel #CHANNEL` set Channel where new members are welcomed"; + } + + @Override + public void execute(GenericEvent event) { + + /////////////////////////////////// + // RESPONDE TO JOIN + /////////////////////////////////// + if (event instanceof GuildMemberJoinEvent){ + logger.debug("Welcome triggered"); + + GuildMemberJoinEvent thisEvent = (GuildMemberJoinEvent) event; + + EmbedBuilder eb = new EmbedBuilder(); + eb.setTitle("Welcome in " + thisEvent.getGuild().getName() + " !"); + eb.setDescription(welcomeMessage.replaceAll("\\$USER", thisEvent.getUser().getName())); + + thisEvent.getGuild().getTextChannelById(welcomeChannel).sendMessage(eb.build()).queue(); + + /////////////////////////////////// + // SETUP + /////////////////////////////////// + } else if (event instanceof GuildMessageReceivedEvent) { + + GuildMessageReceivedEvent thisEvent = (GuildMessageReceivedEvent) event; + + if (!isCommand(thisEvent.getMessage())) + return; + + if(!checkForAdmin(thisEvent.getMember())) { + //STUB + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "SetWelcomeMessage")) { + getConfig().remove("welcomeMessage"); + getConfig().put("welcomeMessage", thisEvent.getMessage().getContentRaw() + .replaceAll("(?is:" + getGuildController().getPREFIX() + command + " SetWelcomeMessage )","")); + + safeConfig(getConfig()); + + thisEvent.getChannel().sendMessage("Set Welcomemessage to: `" + getConfig().get("welcomeMessage").toString() + "`").queue(); + } else if (checkForCommand(thisEvent.getMessage().getContentRaw(), "SetWelcomeChannel")) { + + if (thisEvent.getMessage().getMentionedChannels().size() == 1){ + getConfig().remove("welcomeChannel"); + getConfig().put("welcomeChannel", thisEvent.getMessage().getMentionedChannels().get(0).getIdLong()); + + safeConfig(getConfig()); + + thisEvent.getChannel().sendMessage("Set Welcomechannel to: " + + thisEvent.getGuild().getGuildChannelById(Long.parseLong(getConfig().get("welcomeChannel").toString())).getName()).queue(); + } else { + thisEvent.getChannel().sendMessage("please mention a specific channel!").queue(); + } + } + } + } + + @Override + public String showSettings() { + return "WELCOME-CHANNEL: `" + ((getGuildController().getJda().getGuildChannelById(welcomeChannel) == null) ? "none" : getGuildController().getJda().getGuildChannelById(welcomeChannel).getName()) + "`\n" + + "WELCOME-MESSAGE: `" + welcomeMessage + "`"; + } +} diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..623829e --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,21 @@ +# Root logger option +log4j.rootLogger=TRACE, stdout, FILE +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSS} %-5p [%c] - %m%n + +# Direct log messages to a log file +log4j.appender.FILE=org.apache.log4j.FileAppender +log4j.appender.FILE.File=MissingIdentifier.log +log4j.appender.FILE.MaxFileSize=50MB +log4j.appender.FILE.MaxBackupIndex=10 +log4j.appender.FILE.layout=org.apache.log4j.PatternLayout +log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +log4j.appender.FILE.ImmediateFlush=true +log4j.appender.FILE.Threshold=debug +log4j.appender.FILE.Append=true + +# exclude JDA DEBUG +log4j.logger.net.dv8tion.jda=DEBUG, stdout +#log4j.additivity.net.dv8tion.jda=false \ No newline at end of file