diff --git a/.gitignore b/.gitignore
index d989a4e..3f94ff6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,3 +83,4 @@ fabric.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
fundiscordbot.iml
+./.idea/*
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..a33744a
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,98 @@
+import org.apache.tools.ant.filters.ReplaceTokens
+
+plugins {
+ id 'java'
+ id 'maven-publish'
+ id 'com.github.johnrengelman.shadow' version '4.0.2'
+}
+
+group = 'de.devgruppe'
+version = '0.0.1'
+description = 'FunDiscordBot'
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ maven {
+ url = 'http://jcenter.bintray.com'
+ }
+
+ maven {
+ url = 'http://repo.maven.apache.org/maven2'
+ }
+}
+
+dependencies {
+ implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.0'
+ implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.0'
+
+ compile 'net.dv8tion:JDA:3.4.0_317'
+ compile 'com.google.code.gson:gson:2.8.5'
+ compile 'commons-io:commons-io:2.5'
+
+ compileOnly 'org.projectlombok:lombok:1.18.10'
+ annotationProcessor 'org.projectlombok:lombok:1.18.10'
+}
+
+task sourcesForRelease(type: Copy) {
+ from 'src/main/java'
+ into 'build/filteredSrc'
+ filter(ReplaceTokens, tokens: [VERSION: version, DATE: getBuildDate(), TIME: getBuildTime()])
+}
+
+static def getBuildDate() {
+ return new Date().format('yyyy/MM/dd')
+}
+
+static def getBuildTime() {
+ return new Date().format('HH:mm:ss')
+}
+
+compileJava {
+ options.encoding = 'UTF-8'
+ source = sourcesForRelease.destinationDir
+ classpath = sourceSets.main.compileClasspath
+ dependsOn sourcesForRelease
+}
+
+task sourcesJar(type: Jar, dependsOn: classes) {
+ classifier = 'sources'
+ from "${buildDir}/filteredSrc"
+}
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+}
+
+javadoc {
+ options.encoding = 'UTF-8'
+ if (JavaVersion.current().java9Compatible) {
+ afterEvaluate {
+ options.addBooleanOption("html5", true)
+ }
+ }
+}
+
+jar {
+ baseName = project.name
+}
+
+shadowJar {
+ classifier = 'withDependencies'
+}
+
+build {
+ dependsOn clean
+ dependsOn jar
+ //dependsOn javadocJar
+ dependsOn sourcesJar
+ dependsOn shadowJar
+
+ jar.mustRunAfter clean
+ javadocJar.mustRunAfter jar
+ //sourcesJar.mustRunAfter javadocJar
+ shadowJar.mustRunAfter sourcesJar
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..d2540fc
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,11 @@
+#Enable daemon
+org.gradle.daemon=true
+
+# Try and findout the best heap size for your project build.
+org.gradle.jvmargs=-Xmx3096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# Modularise your project and enable parallel build
+org.gradle.parallel=true
+
+# Enable configure on demand.
+org.gradle.configureondemand=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..8d27651
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Oct 04 15:17:45 CEST 2019
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-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..83f2acf
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,188 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## 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='"-Xmx64m" "-Xms64m"'
+
+# 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 or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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..9618d8d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@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="-Xmx64m" "-Xms64m"
+
+@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/pom.xml b/pom.xml
deleted file mode 100644
index e438d89..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
- 4.0.0
-
- de.devgruppe
- fundiscordbot
- FunDiscordBot
- 0.0.1
- jar
-
-
- This application is developed by the DevGruppe members for fun.
-
-
- de.devgruppe.fundiscordbot.FunDiscordBotStarter
- UTF-8
- UTF-8
-
-
-
-
- jcenter
- jcenter-bintray
- http://jcenter.bintray.com
-
-
-
-
-
- log4j
- log4j
- 1.2.17
- compile
-
-
- org.projectlombok
- lombok
- 1.16.16
- provided
-
-
- net.dv8tion
- JDA
- LATEST
- compile
-
-
- com.google.code.gson
- gson
- LATEST
-
-
- commons-io
- commons-io
- 2.5
-
-
-
-
- src/main/java
-
-
-
- .
- true
- src/main/resources
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.0.2
-
-
-
- ${main.class}
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.3
-
- 1.8
- 1.8
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.4.3
-
-
- package
-
- shade
-
-
-
-
- false
- true
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 2.6
-
-
-
-
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..1d7d688
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'fundiscordbot'
diff --git a/src/main/java/de/devgruppe/fundiscordbot/FunDiscordBotStarter.java b/src/main/java/de/devgruppe/fundiscordbot/FunDiscordBotStarter.java
index 8ef26a8..109274d 100644
--- a/src/main/java/de/devgruppe/fundiscordbot/FunDiscordBotStarter.java
+++ b/src/main/java/de/devgruppe/fundiscordbot/FunDiscordBotStarter.java
@@ -9,7 +9,7 @@
import de.devgruppe.fundiscordbot.command.impl.DefaultCommandRegistry;
import de.devgruppe.fundiscordbot.config.Config;
import de.devgruppe.fundiscordbot.config.Configuration;
-
+import lombok.Getter;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
@@ -18,14 +18,11 @@
import net.dv8tion.jda.core.events.ReadyEvent;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
import net.dv8tion.jda.core.hooks.EventListener;
-
-import org.apache.log4j.Logger;
-
-import java.util.Scanner;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import javax.security.auth.login.LoginException;
-
-import lombok.Getter;
+import java.util.Scanner;
public class FunDiscordBotStarter implements EventListener {
@@ -54,19 +51,20 @@ private FunDiscordBotStarter() {
configuration.readConfiguration();
config = configuration.getConfig();
this.commandRegistry = new DefaultCommandRegistry();
- logger.info("Connecting...");
+ logger.info("Connecting to discord server...");
try {
jda = new JDABuilder(AccountType.BOT)
.setToken(this.config.getBotToken())
.setAutoReconnect(true)
.addEventListener(this)
- .setGame(Game.of("https://github.com/Dev-Gruppe/FunDiscordBot", "https://github.com/Dev-Gruppe/FunDiscordBot"))
+ .setGame(
+ Game.of("https://github.com/Dev-Gruppe/FunDiscordBot", "https://github.com/Dev-Gruppe/FunDiscordBot"))
.buildAsync();
} catch (LoginException | RateLimitedException e) {
e.printStackTrace();
}
if (jda == null) {
- logger.error("JDA is null");
+ logger.error("JDA is null. Shutting down...");
System.exit(0);
}
this.jda.addEventListener(this.commandRegistry);
@@ -74,12 +72,13 @@ private FunDiscordBotStarter() {
}
public static void main(String[] args) {
- logger = Logger.getLogger("FunDiscordBot");
+ logger = LogManager.getLogger("FunDiscordBot");
new FunDiscordBotStarter();
}
private void registerCommands() {
- this.commandRegistry.registerCommand(new CommandListCommand());
+ final CommandListCommand commandListCommand = new CommandListCommand();
+ this.commandRegistry.registerCommand(commandListCommand);
this.commandRegistry.registerCommand(new EchoCommand());
this.commandRegistry.registerCommand(new RandomCommand());
this.commandRegistry.registerCommand(new CountCommand());
@@ -88,12 +87,15 @@ private void registerCommands() {
this.commandRegistry.registerCommand(new RandomGiphyCommand());
this.commandRegistry.registerCommand(new TrendingGiphyCommand());
this.commandRegistry.registerCommand(new PingCommand());
+ this.commandRegistry.registerCommand(new StatusCommand());
+ this.commandRegistry.registerCommand(new UserInfoCommand());
+ commandListCommand.initialize();
}
@Override
public void onEvent(Event event) {
if (event instanceof ReadyEvent) {
- logger.info("Connected");
+ logger.info("Connected to discord server!");
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
String line;
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/commands/CommandListCommand.java b/src/main/java/de/devgruppe/fundiscordbot/command/commands/CommandListCommand.java
index 610a8ea..31d5ccb 100644
--- a/src/main/java/de/devgruppe/fundiscordbot/command/commands/CommandListCommand.java
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/commands/CommandListCommand.java
@@ -1,33 +1,159 @@
package de.devgruppe.fundiscordbot.command.commands;
+import de.devgruppe.fundiscordbot.Constants;
import de.devgruppe.fundiscordbot.FunDiscordBotStarter;
import de.devgruppe.fundiscordbot.command.Command;
-import de.devgruppe.fundiscordbot.command.CommandRegistry;
import de.devgruppe.fundiscordbot.command.CommandResponse;
+
+import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.Message;
+import net.dv8tion.jda.core.entities.MessageEmbed;
+import net.dv8tion.jda.core.entities.TextChannel;
+import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
+import net.dv8tion.jda.core.hooks.ListenerAdapter;
+import net.dv8tion.jda.core.requests.RestAction;
+
+import java.awt.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
/**
* Created by GalaxyHD on 12.09.2017.
*/
public class CommandListCommand extends Command {
+ private LinkedList cachedMessageEmbedMap = new LinkedList<>();
+
+ private Map registeredHelpCommandMessages = new HashMap<>();
+ private static final String ARROW_RIGHT_EMOTE = new String(new byte[]{-30, -98, -95}, StandardCharsets.UTF_8);
+ private static final String ARROW_LEFT_EMOTE = new String(new byte[]{-30, -84, -123}, StandardCharsets.UTF_8);
+
+ private static final int ITEM_AMOUNT_PER_SITE = 4;
public CommandListCommand() {
- super("commandlist", "", "Gibt dir eine Übersicht von allen Befehlen");
+ super("commandlist", "", "Gibt dir eine Übersicht von allen Befehlen aus.");
+ }
+
+ public void initialize() {
+ FunDiscordBotStarter.getInstance().getJda().addEventListener(new CommandListReactionListener());
+ int site = 0;
+ int iterateTo;
+ final List commandList = FunDiscordBotStarter.getInstance().getCommandRegistry().getRegisteredCommands();
+ do {
+ site++;
+ final EmbedBuilder embedBuilder = new EmbedBuilder().setColor(Color.GRAY).setTitle("Befehlsübersicht")
+ .setFooter("Seite " + String.valueOf(site), null);
+ iterateTo = addCommandsToMessageEmbed(site, embedBuilder, commandList);
+ final MessageEmbed messageEmbed = embedBuilder.build();
+ this.cachedMessageEmbedMap.add(messageEmbed);
+ } while (iterateTo < commandList.size());
+ }
+
+ private int addCommandsToMessageEmbed(int site, EmbedBuilder embedBuilder, List commandList) {
+ final int offset = (site - 1) * ITEM_AMOUNT_PER_SITE;
+ final int iterateTo = offset + ITEM_AMOUNT_PER_SITE;
+ if (offset == iterateTo) {
+ throw new IllegalStateException("Can not display site " + site + " because it would not contain any item!");
+ }
+ for (int i = offset; i < iterateTo && i != commandList.size(); i++) {
+ final Command command = commandList.get(i);
+ embedBuilder.addField(FunDiscordBotStarter.getInstance().getCommandRegistry().getPrefix() + command.getCommandName(),
+ command.getDescription(), false);
+ }
+ return iterateTo;
}
@Override
public CommandResponse triggerCommand(Message message, String[] args) {
- StringBuilder stringBuilder = new StringBuilder();
- CommandRegistry commandRegistry = FunDiscordBotStarter.getInstance().getCommandRegistry();
- stringBuilder.append("Befehle: \n");
- stringBuilder.append("```");
- commandRegistry.getRegisteredCommands().forEach(command -> stringBuilder.append(commandRegistry.getPrefix())
- .append(command.getCommandName())
- .append(" - ")
- .append(command.getDescription())
- .append("\n"));
- stringBuilder.append("```");
- message.getTextChannel().sendMessage(stringBuilder.toString()).complete();
+ this.displayCommandListSite(message.getTextChannel());
return CommandResponse.ACCEPTED;
}
+
+ private void displayCommandListSite(final TextChannel textChannel) {
+ this.displayCommandListSite(1, textChannel, null);
+ }
+
+ private void displayCommandListSite(final int site, final TextChannel textChannel, final Message editMessage) {
+ final MessageEmbed messageEmbed = this.cachedMessageEmbedMap.get(site - 1);
+ final RestAction restAction;
+ if (editMessage != null) {
+ restAction = editMessage.editMessage(messageEmbed);
+ } else {
+ restAction = textChannel.sendMessage(messageEmbed);
+ }
+ restAction.queue(message -> {
+ if (site > 1) {
+ message.addReaction(ARROW_LEFT_EMOTE).queue(ignoredVoid -> {
+ if (site < CommandListCommand.this.cachedMessageEmbedMap.size()) {
+ message.addReaction(ARROW_RIGHT_EMOTE).queue(new PutMessageMapConsumer(message, site));
+ } else {
+ new PutMessageMapConsumer(message, site).accept(null);
+ }
+ });
+ } else {
+ message.addReaction(ARROW_RIGHT_EMOTE).queue(new PutMessageMapConsumer(message, site));
+ }
+ });
+ }
+
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ private class PutMessageMapConsumer implements Consumer {
+ private final Message message;
+ private final int site;
+
+ @Override
+ public void accept(Void ignoredVoid) {
+ CommandListCommand.this.registeredHelpCommandMessages.put(this.message, this.site);
+ Constants.EXECUTOR_SERVICE.execute(() -> {
+ try {
+ Thread.sleep(TimeUnit.SECONDS.toMillis(60));
+ PutMessageMapConsumer.this.message.clearReactions().queue(anotherIgnoredVoid ->
+ CommandListCommand.this.registeredHelpCommandMessages.remove(PutMessageMapConsumer.this.message));
+ } catch (InterruptedException e) {
+ FunDiscordBotStarter.getLogger().error("There was an error while sleeping until the help messages gets removed.", e);
+ }
+ });
+ }
+ }
+
+ private class CommandListReactionListener extends ListenerAdapter {
+ @Override
+ public void onMessageReactionAdd(MessageReactionAddEvent event) {
+ final int currentSite;
+ generalMessageCheck:
+ {
+ for (Message message : CommandListCommand.this.registeredHelpCommandMessages.keySet()) {
+ if (message.getTextChannel().getId().equals(event.getTextChannel().getId()) &&
+ message.getId().equals(event.getMessageId())) {
+ currentSite = CommandListCommand.this.registeredHelpCommandMessages.get(message);
+ break generalMessageCheck;
+ }
+ }
+ return;
+ }
+ if (event.getReaction().isSelf()) return;
+ event.getReaction().getUsers().queue(users -> {
+ if (!users.contains(event.getJDA().getSelfUser())) return;
+ String reactionName = event.getReaction().getEmote().getName();
+ final int newSite;
+ if (reactionName.equals(ARROW_LEFT_EMOTE)) {
+ newSite = currentSite - 1;
+ } else if (reactionName.equals(ARROW_RIGHT_EMOTE)) {
+ newSite = currentSite + 1;
+ } else {
+ return;
+ }
+ event.getTextChannel().getMessageById(event.getMessageId()).queue(editMessage ->
+ editMessage.clearReactions().queue(ignoredVoid ->
+ CommandListCommand.this.displayCommandListSite(newSite, event.getTextChannel(), editMessage)));
+ });
+ }
+ }
}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/commands/PingCommand.java b/src/main/java/de/devgruppe/fundiscordbot/command/commands/PingCommand.java
index 6820937..0ce7d2d 100644
--- a/src/main/java/de/devgruppe/fundiscordbot/command/commands/PingCommand.java
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/commands/PingCommand.java
@@ -4,12 +4,14 @@
import de.devgruppe.fundiscordbot.FunDiscordBotStarter;
import de.devgruppe.fundiscordbot.command.Command;
import de.devgruppe.fundiscordbot.command.CommandResponse;
+import de.devgruppe.fundiscordbot.cooldown.ICooldown;
+import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.Message;
/**
* Created by GalaxyHD on 26.09.2017.
*/
-public class PingCommand extends Command {
+public class PingCommand extends Command implements ICooldown {
private static final int COUNT = 8;
@@ -28,11 +30,11 @@ public PingCommand() {
public CommandResponse triggerCommand(Message message, String[] args) {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("nice")) {
- Constants.EXECUTOR_SERVICE.execute(() -> message.getTextChannel().sendMessage("Ping...").queue(pingMessage -> {
+ message.getTextChannel().sendMessage("Ping...").queue(pingMessage -> Constants.EXECUTOR_SERVICE.execute(() -> {
long lastResult;
long sum = 0, min = 999, max = 0;
for (int i = 0; i < COUNT; i++) {
- pingMessage.editMessage(pingMessages[i % pingMessages.length]).complete();
+ pingMessage.editMessage(pingMessages[i % pingMessages.length]).queue();
lastResult = FunDiscordBotStarter.getInstance().getJda().getPing();
sum += lastResult;
min = Math.min(min, lastResult);
@@ -44,7 +46,9 @@ public CommandResponse triggerCommand(Message message, String[] args) {
}
}
pingMessage.editMessage(
- String.format("Durchschnittlicher Ping %dms (min: %d, max: %d)", (int) Math.ceil(sum / COUNT), min, max))
+ String
+ .format("Durchschnittlicher Ping %dms (min: %d, max: %d)", (int) Math.ceil((double) sum / COUNT), min,
+ max))
.complete();
}));
return CommandResponse.ACCEPTED;
@@ -56,4 +60,13 @@ public CommandResponse triggerCommand(Message message, String[] args) {
return CommandResponse.ACCEPTED;
}
+ @Override
+ public boolean bypassCooldown(Member member) {
+ return member.getUser().getId().equals("127528375643406336");
+ }
+
+ @Override
+ public int cooldownDuration() {
+ return 20;
+ }
}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/commands/StatusCommand.java b/src/main/java/de/devgruppe/fundiscordbot/command/commands/StatusCommand.java
new file mode 100644
index 0000000..d8ff738
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/commands/StatusCommand.java
@@ -0,0 +1,38 @@
+package de.devgruppe.fundiscordbot.command.commands;
+
+import de.devgruppe.fundiscordbot.FunDiscordBotStarter;
+import de.devgruppe.fundiscordbot.command.Command;
+import de.devgruppe.fundiscordbot.command.CommandResponse;
+import net.dv8tion.jda.core.EmbedBuilder;
+import net.dv8tion.jda.core.JDA;
+import net.dv8tion.jda.core.JDAInfo;
+import net.dv8tion.jda.core.entities.Message;
+
+public class StatusCommand extends Command {
+
+ public StatusCommand() {
+ super("status", "", "Bot information");
+ }
+
+ @Override
+ public CommandResponse triggerCommand(final Message message, final String[] args) {
+ JDA jda = message.getJDA();
+ final FunDiscordBotStarter instance = FunDiscordBotStarter.getInstance();
+ EmbedBuilder embedBuilder = new EmbedBuilder()
+ .setAuthor("Information", null, jda.getSelfUser().getEffectiveAvatarUrl())
+ .setColor(message.getGuild().getSelfMember().getColor());
+ embedBuilder.addField("JDA Version", JDAInfo.VERSION, true);
+ embedBuilder.addField("Java Version", System.getProperty("java.runtime.version").replace("+", "_"), true);
+ embedBuilder.addField("Guilds", String.valueOf(jda.getGuilds().size()), true);
+ embedBuilder.addField("Ping", String.valueOf(jda.getPing()), true);
+ embedBuilder.addField("Total Responses", String.valueOf(jda.getResponseTotal()), true);
+ embedBuilder
+ .addField("Commands", String.valueOf(instance.getCommandRegistry().getRegisteredCommands().size()), true);
+ embedBuilder.addField("Total Users", String.valueOf(jda.getUserCache().size()), true);
+ embedBuilder.addField("JDA Status", jda.getStatus().name(), true);
+ embedBuilder.addField("WebSocketTrace", String.valueOf(jda.getWebSocketTrace().size()), true);
+ embedBuilder.addField("CloudflareRays", String.valueOf(jda.getCloudflareRays().size()), true);
+ message.getTextChannel().sendMessage(embedBuilder.build()).queue();
+ return CommandResponse.ACCEPTED;
+ }
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/commands/UserInfoCommand.java b/src/main/java/de/devgruppe/fundiscordbot/command/commands/UserInfoCommand.java
new file mode 100644
index 0000000..b9d0883
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/commands/UserInfoCommand.java
@@ -0,0 +1,96 @@
+package de.devgruppe.fundiscordbot.command.commands;
+
+import de.devgruppe.fundiscordbot.command.Command;
+import de.devgruppe.fundiscordbot.command.CommandResponse;
+import net.dv8tion.jda.core.EmbedBuilder;
+import net.dv8tion.jda.core.entities.Guild;
+import net.dv8tion.jda.core.entities.Member;
+import net.dv8tion.jda.core.entities.Message;
+import net.dv8tion.jda.core.entities.User;
+import net.dv8tion.jda.core.utils.MiscUtil;
+
+import java.text.MessageFormat;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+
+public class UserInfoCommand extends Command {
+
+ public UserInfoCommand() {
+ super("userinfo", "", "User information");
+ }
+
+ @Override
+ public CommandResponse triggerCommand(Message message, String[] args) {
+ if (args.length < 1)
+ return CommandResponse.SYNTAX_PRINTED;
+ Member member = getMember(message.getGuild(), args[0]);
+ if (member == null) {
+ message.getChannel().sendMessage("Member not found.").complete();
+ return CommandResponse.ACCEPTED;
+ }
+ EmbedBuilder embedBuilder = new EmbedBuilder();
+ embedBuilder.setColor(member.getColor());
+ User user = member.getUser();
+ String onlineStatus = member.getOnlineStatus().name();
+ String game = (member.getGame() != null ? member.getGame().getName() : "No game");
+ String accountCreation = MiscUtil.getDateTimeString(MiscUtil.getCreationTime(user));
+
+ List joins = new ArrayList<>(message.getGuild().getMembers());
+ joins.sort(Comparator.comparing(Member:: getJoinDate));
+ String joinPosition = String.valueOf(joins.indexOf(member) + 1);
+
+ String joinDate = member.getJoinDate().format(DateTimeFormatter.RFC_1123_DATE_TIME);
+ String joinOrder = getJoinOrder(member, joins);
+
+ embedBuilder.setThumbnail(user.getEffectiveAvatarUrl());
+
+ embedBuilder.setAuthor(MessageFormat.format("Userinfo for {0} ({1})", user.getName(), user.getId()),
+ user.getEffectiveAvatarUrl(), user.getEffectiveAvatarUrl());
+ embedBuilder.addField("Status", onlineStatus, true);
+ embedBuilder.addField("Game", game, true);
+ embedBuilder.addField("IsBot", String.valueOf(user.isBot()), true);
+ embedBuilder.addField("Account Creation", accountCreation, true);
+ embedBuilder.addField("Join Position", joinPosition, true);
+ embedBuilder.addField("Join Date", joinDate, true);
+ embedBuilder.addField("Nickname", member.getEffectiveName(), true);
+ embedBuilder.addField("Join Order", joinOrder, true);
+ message.getChannel().sendMessage(embedBuilder.build()).complete();
+ return CommandResponse.ACCEPTED;
+ }
+
+ private String getJoinOrder(Member member, List joins) {
+ StringBuilder joinOrder = new StringBuilder();
+ int index = joins.indexOf(member);
+ index -= 3;
+ if (index < 0)
+ index = 0;
+ if (joins.get(index).equals(member))
+ joinOrder.append("**").append(joins.get(index).getUser().getName()).append("**");
+ else
+ joinOrder.append(joins.get(index).getUser().getName());
+ for (int i = index + 1; i < index + 7; i++) {
+ if (i >= joins.size())
+ break;
+ Member joinMember = joins.get(i);
+ String name = joinMember.getUser().getName();
+ if (joinMember.equals(member))
+ name = "**" + name + "**";
+ joinOrder.append(" > ").append(name);
+ }
+ return joinOrder.toString();
+ }
+
+ private Member getMember(Guild guild, String name) {
+ Optional optional = guild.
+ getMembers()
+ .stream()
+ .filter(member -> member.getUser().getName().toLowerCase().startsWith(name.toLowerCase()) ||
+ (member.getNickname() != null && member.getNickname().toLowerCase().startsWith(name.toLowerCase())))
+ .findFirst();
+ return optional.orElse(null);
+ }
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/commands/memegen/MemeGenCommand.java b/src/main/java/de/devgruppe/fundiscordbot/command/commands/memegen/MemeGenCommand.java
index bca7f35..c5ec870 100644
--- a/src/main/java/de/devgruppe/fundiscordbot/command/commands/memegen/MemeGenCommand.java
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/commands/memegen/MemeGenCommand.java
@@ -16,6 +16,8 @@
import java.awt.*;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class MemeGenCommand extends Command {
@@ -40,32 +42,36 @@ private CommandResponse performMemeRequest(final Message message, final String[]
return CommandResponse.SYNTAX_PRINTED;
}
final StringBuilder urlRequest = new StringBuilder();
- urlRequest.append(args[0]).append("/");
+ urlRequest.append(URLEncoder.encode(args[0], StandardCharsets.UTF_8.toString())).append("/");
if (args.length >= 2) {
final String text = this.getEscapedText(String.join(" ", Arrays.copyOfRange(args, 1, args.length)))
- .replaceAll(" +", " ");
+ .replaceAll(" +", "_");
final String[] splitText = text.split(";");
+ for (int i = 0; i < splitText.length; i++) {
+ splitText[i] = URLEncoder.encode(splitText[i], StandardCharsets.UTF_8.toString());
+ }
if (splitText.length == 2) {
urlRequest.append(splitText[0]).append("/").append(splitText[1]);
} else if (splitText.length == 1) {
- urlRequest.append(text);
+ urlRequest.append(splitText[0]);
} else {
message.getTextChannel().sendMessage("Es darf maximal ein Semikolon(``;``) in deine Nachricht enthalten sein.").queue();
return CommandResponse.ACCEPTED;
}
+ final String url = MemeGenHelper.REQUEST_URL + MemeGenHelper.TEMPLATE_PATH + urlRequest.toString().toLowerCase();
final HttpRequest.RequestResponse response = HttpRequest.performRequest(new HttpRequest.RequestBuilder(
- MemeGenHelper.REQUEST_URL + MemeGenHelper.TEMPLATE_PATH + urlRequest.toString().toLowerCase(), HttpRequest.HttpRequestMethod.GET)
+ url, HttpRequest.HttpRequestMethod.GET)
.addHeader(MemeGenHelper.REQUEST_HEADERS[0], MemeGenHelper.REQUEST_HEADERS[1])
.addHeader(MemeGenHelper.REQUEST_HEADERS[2], MemeGenHelper.REQUEST_HEADERS[3])
.setReadTimeout(FunDiscordBotStarter.getInstance().getConfig().getMemeTimeout()));
if (response.getStatus() == GiphyHelper.EXPECTED_RESPONSE_CODE) {
final JsonElement jsonElement = new JsonParser().parse(response.getResultMessage());
final JsonObject jsonObject = jsonElement.getAsJsonObject().getAsJsonObject(JSON_DIRECT_KEY);
- final String url = jsonObject.get(JSON_MASKED_KEY).getAsString();
- message.getTextChannel().sendMessage(new EmbedBuilder().setColor(Color.GREEN).setTitle(" ").setImage(url)
+ final String memeUrl = jsonObject.get(JSON_MASKED_KEY).getAsString();
+ message.getTextChannel().sendMessage(new EmbedBuilder().setColor(Color.GREEN).setTitle(" ").setImage(memeUrl)
.addField("Meme-Name", args[0], true)
.addField("Erstellt von", message.getAuthor().getName(), true)
- .addField("URL", url, true).build()).queue();
+ .addField("URL", memeUrl, true).build()).queue();
return CommandResponse.ACCEPTED;
} else {
FunDiscordBotStarter.getLogger().warn("The memegen.link server returned an unexpected HTTP Status code (" + response.getStatus() + "): " + response.getResultMessage());
diff --git a/src/main/java/de/devgruppe/fundiscordbot/command/impl/DefaultCommandRegistry.java b/src/main/java/de/devgruppe/fundiscordbot/command/impl/DefaultCommandRegistry.java
index 637e008..8c903a0 100644
--- a/src/main/java/de/devgruppe/fundiscordbot/command/impl/DefaultCommandRegistry.java
+++ b/src/main/java/de/devgruppe/fundiscordbot/command/impl/DefaultCommandRegistry.java
@@ -1,8 +1,13 @@
package de.devgruppe.fundiscordbot.command.impl;
+import de.devgruppe.fundiscordbot.FunDiscordBotStarter;
import de.devgruppe.fundiscordbot.command.Command;
import de.devgruppe.fundiscordbot.command.CommandRegistry;
import de.devgruppe.fundiscordbot.command.CommandResponse;
+import de.devgruppe.fundiscordbot.cooldown.CooldownManager;
+import de.devgruppe.fundiscordbot.cooldown.CooldownResponse;
+import de.devgruppe.fundiscordbot.cooldown.ICooldown;
+
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
@@ -12,6 +17,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
* Created by GalaxyHD on 11.09.2017.
@@ -51,12 +57,27 @@ public void onMessageReceived(MessageReceivedEvent event) {
message.getTextChannel().sendMessage("Der Command wurde nicht gefunden.").complete();
return;
}
+ if (command instanceof ICooldown) {
+ CooldownManager cooldownManager = CooldownManager.getInstance();
+ ICooldown cooldown = (ICooldown) command;
+ CooldownResponse cooldownResponse = cooldownManager.hasCooldown(command, event.getMember());
+ if (cooldownResponse == CooldownResponse.TRUE) {
+ message.getTextChannel()
+ .sendMessage(String.format("Du hast noch ein Cooldown `(%d sec)`. Bitte warte noch etwas.",
+ cooldown.cooldownDuration()))
+ .queue(message1 -> message1.delete().completeAfter(5, TimeUnit.SECONDS));
+ return;
+ } else if (cooldownResponse == CooldownResponse.FALSE) {
+ cooldownManager.addCooldown(command, message.getMember());
+ }
+ }
+ FunDiscordBotStarter.getLogger().info(String.format("Command - %s#%s - %s", event.getAuthor().getName(), event.getAuthor().getId(), content));
CommandResponse commandResponse = command.triggerCommand(message, args);
if (commandResponse == CommandResponse.SYNTAX_PRINTED)
message.getTextChannel()
- .sendMessage(
- MessageFormat.format("Syntax: `{0}{1} {2}`", PREFIX, command.getCommandName(), command.getSyntax()))
- .complete();
+ .sendMessage(
+ MessageFormat.format("Syntax: `{0}{1} {2}`", PREFIX, command.getCommandName(), command.getSyntax()))
+ .complete();
}
@Override
@@ -67,9 +88,9 @@ public Command getCommandObjectByClass(Class extends Command> commandClass) {
@Override
public Command getCommandObjectByName(String commandName) {
return this.commands.stream()
- .filter(command -> command.getCommandName().equalsIgnoreCase(commandName))
- .findFirst()
- .orElse(null);
+ .filter(command -> command.getCommandName().equalsIgnoreCase(commandName))
+ .findFirst()
+ .orElse(null);
}
@Override
diff --git a/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownEntry.java b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownEntry.java
new file mode 100644
index 0000000..aa27bff
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownEntry.java
@@ -0,0 +1,40 @@
+package de.devgruppe.fundiscordbot.cooldown;
+
+import lombok.Getter;
+import net.dv8tion.jda.core.entities.Member;
+
+import java.util.HashMap;
+
+/**
+ * Created by GalaxyHD on 28.09.2017.
+ */
+public class CooldownEntry {
+
+ private HashMap cooldowns = new HashMap<>();
+ @Getter
+ private int length;
+
+ public CooldownEntry(int length) {
+ this.length = length;
+ }
+
+ public void addMember(Member member) {
+ if (!containsMember(member))
+ cooldowns.put(member.getUser().getId(), System.currentTimeMillis());
+ }
+
+ public void removeMember(Member member) {
+ if (containsMember(member))
+ cooldowns.remove(member.getUser().getId());
+ }
+
+ public boolean containsMember(Member member) {
+ return cooldowns.containsKey(member.getUser().getId());
+ }
+
+ public long getCooldownStart(Member member) {
+ if (!containsMember(member)) return -1;
+ return cooldowns.get(member.getUser().getId());
+ }
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownManager.java b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownManager.java
new file mode 100644
index 0000000..74e0acb
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownManager.java
@@ -0,0 +1,55 @@
+package de.devgruppe.fundiscordbot.cooldown;
+
+import de.devgruppe.fundiscordbot.FunDiscordBotStarter;
+import de.devgruppe.fundiscordbot.command.Command;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import net.dv8tion.jda.core.entities.Member;
+
+import java.util.HashMap;
+
+/**
+ * Created by GalaxyHD on 28.09.2017.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class CooldownManager {
+ @Getter
+ private static CooldownManager instance = new CooldownManager();
+
+ private HashMap commandCooldowns = new HashMap<>();
+
+ public CooldownResponse hasCooldown(Command command, Member member) {
+ if (!(command instanceof ICooldown)) return CooldownResponse.FALSE;
+ ICooldown cooldown = (ICooldown) command;
+ if (cooldown.bypassCooldown(member)) return CooldownResponse.BYPASS;
+ if (!commandCooldowns.containsKey(command)) return CooldownResponse.FALSE;
+ CooldownEntry cooldownEntry = commandCooldowns.get(command);
+ if (!cooldownEntry.containsMember(member)) return CooldownResponse.FALSE;
+ long end = cooldownEntry.getLength() * 1000 + cooldownEntry.getCooldownStart(member);
+ boolean flag = System.currentTimeMillis() < end;
+ if (!flag) removeCooldown(command, member);
+ return flag ? CooldownResponse.TRUE : CooldownResponse.FALSE;
+ }
+
+ public void addCooldown(Command command, Member member) {
+ if (!(command instanceof ICooldown)) return;
+ ICooldown cooldown = (ICooldown) command;
+ CooldownEntry cooldownEntry = null;
+ if (!commandCooldowns.containsKey(command)) {
+ cooldownEntry = commandCooldowns.put(command, new CooldownEntry(cooldown.cooldownDuration()));
+ }
+ if (cooldownEntry == null) cooldownEntry = commandCooldowns.get(command);
+ cooldownEntry.addMember(member);
+ FunDiscordBotStarter.getLogger().debug("Add Cooldown to " + member.getNickname());
+ }
+
+ public void removeCooldown(Command command, Member member) {
+ if (!(command instanceof ICooldown)) return;
+ if (!commandCooldowns.containsKey(command)) return;
+ CooldownEntry cooldownEntry = commandCooldowns.get(command);
+ cooldownEntry.removeMember(member);
+ FunDiscordBotStarter.getLogger().debug("Remove Cooldown from " + member.getNickname());
+ }
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownResponse.java b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownResponse.java
new file mode 100644
index 0000000..948229c
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/cooldown/CooldownResponse.java
@@ -0,0 +1,12 @@
+package de.devgruppe.fundiscordbot.cooldown;
+
+/**
+ * Created by GalaxyHD on 29.09.2017.
+ */
+public enum CooldownResponse {
+
+ TRUE,
+ FALSE,
+ BYPASS
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/cooldown/ICooldown.java b/src/main/java/de/devgruppe/fundiscordbot/cooldown/ICooldown.java
new file mode 100644
index 0000000..843be9a
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/cooldown/ICooldown.java
@@ -0,0 +1,26 @@
+package de.devgruppe.fundiscordbot.cooldown;
+
+import net.dv8tion.jda.core.entities.Member;
+
+/**
+ * Created by GalaxyHD on 28.09.2017.
+ * This class is used to configure a cooldown for a command
+ */
+public interface ICooldown {
+
+ /**
+ * This method is used to allow cooldown bypasses.
+ *
+ * @param member the member object from the JDA api.
+ * @return if the member is allow to bypass the cooldown.
+ */
+ boolean bypassCooldown(Member member);
+
+ /**
+ * This method is used to set the cooldown duration.
+ *
+ * @return the duration from the cooldown in seconds.
+ */
+ int cooldownDuration();
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/utils/MessageCollector.java b/src/main/java/de/devgruppe/fundiscordbot/utils/MessageCollector.java
new file mode 100644
index 0000000..4c174bd
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/utils/MessageCollector.java
@@ -0,0 +1,17 @@
+package de.devgruppe.fundiscordbot.utils;
+
+import net.dv8tion.jda.core.entities.Message;
+
+import java.util.List;
+
+public interface MessageCollector {
+
+ void onStart();
+
+ void onEnd(final List messages);
+
+ void onMessageCollect(final Message message, final int position);
+
+ boolean checkStop(final Message message, final int position);
+
+}
diff --git a/src/main/java/de/devgruppe/fundiscordbot/utils/MessagesFetcher.java b/src/main/java/de/devgruppe/fundiscordbot/utils/MessagesFetcher.java
new file mode 100644
index 0000000..85152d4
--- /dev/null
+++ b/src/main/java/de/devgruppe/fundiscordbot/utils/MessagesFetcher.java
@@ -0,0 +1,51 @@
+package de.devgruppe.fundiscordbot.utils;
+
+import de.devgruppe.fundiscordbot.Constants;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import net.dv8tion.jda.core.entities.Message;
+import net.dv8tion.jda.core.entities.TextChannel;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MessagesFetcher {
+
+ public static void getMessages(final TextChannel textChannel, final MessageCollector collector) {
+ Constants.EXECUTOR_SERVICE.execute(() -> {
+ final AtomicInteger counter = new AtomicInteger(0);
+ collector.onStart();
+ CollectResult result = getAllMessages(textChannel, collector, counter);
+ final List messages = result.getMessages();
+ messages.sort(Comparator.comparing(Message::getCreationTime));
+ collector.onEnd(messages);
+ });
+ }
+
+ private static CollectResult getAllMessages(final TextChannel textChannel, final MessageCollector collector,
+ final AtomicInteger counter) {
+ final List messages = new ArrayList<>();
+ boolean forceBreak = false;
+ for (final Message message : textChannel.getIterableHistory().cache(false)) {
+ messages.add(message);
+ counter.addAndGet(1);
+ collector.onMessageCollect(message, counter.get());
+ if (collector.checkStop(message, counter.get())) {
+ forceBreak = true;
+ break;
+ }
+ }
+ return new CollectResult(messages, forceBreak);
+ }
+
+
+ @AllArgsConstructor
+ @Getter
+ private static class CollectResult {
+ private final List messages;
+ private boolean forceBreak;
+ }
+
+}
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
index 4f9f0a1..f1b37a8 100644
--- a/src/main/resources/log4j.properties
+++ b/src/main/resources/log4j.properties
@@ -1,16 +1,13 @@
# Root logger option
-log4j.rootLogger=INFO, stdout, file
-
+log4j.rootLogger=INFO, stdout, File
# Redirect log messages to console
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 HH:mm:ss} %-5p - %m%n
-
# Redirect log messages to a log file, support file rolling.
-log4j.appender.file=org.apache.log4j.RollingFileAppender
-log4j.appender.file.File=logs/application.log
-log4j.appender.file.MaxFileSize=5MB
-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 - %m%n
+log4j.appender.File=org.apache.log4j.rolling.RollingFileAppender
+log4j.appender.File.rollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
+log4j.appender.File.rollingPolicy.FileNamePattern=logs/fundiscordbot-%d{yyyyMMdd-HHmm}.log
+log4j.appender.File.layout=org.apache.log4j.PatternLayout
+log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n