diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..4bebb25 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: fr.neutronstars.nbot.NBotStart + diff --git a/README.md b/README.md new file mode 100644 index 0000000..cabe186 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# __**[** *N-Bot API* **]**__ + +N-Bot API is an __*open-source project*__ using **JDA** which will allow you **create/personalize** your bots simplest through a plugin system. + +For use it download the [latest release](https://github.com/NeutronStars/N-Bot/releases) and execute the following command `java -jar N-Bot-VERSION-withDependencies-JDA-VERSION.jar` a **config** folder will appear who contains an **config.json** file. Open it and insert your bot **token**, now you can re-execute the previous command, folders are going to generate. When you want to stop the bot, just print `stop` in the console. + +For create a **plugin**, add the **N-Bot API** on your project libraries, your main class will need to extends **NBotPlugin** who contains `onLoad()`, `onEnable()` and `onDisable()` methods with `@Override` annotation. + +```java +public class MyPlugin extends NBotPlugin +{ + public MyPlugin() + { + super("Author"); + } + + @Override + public void onLoad() + { + NBot.getLogger().log("MyPlugin is loaded."); + } + + @Override + public void onLoad() + { + NBot.getLogger().log("MyPlugin is enabled."); + } + + @Override + public void onDisable() + { + NBot.getLogger().log("MyPlugin is disabled."); + } +} +``` + +You can too create commands, create a class and insert methods with **@Command** annotation like this. + +```java +import fr.neutronstars.nbot.entity.User; +import fr.neutronstars.nbot.entity.Channel; +import fr.neutronstars.nbot.entity.Message; + +public class MyCommand +{ + @Command(name="info",description="Shows the bot informations.",powers=10) + public void onInfo(User user, Channel channel, Message message) + { + //Your Code. + } +} +``` + +and register your command class in the `onEnable()` method like this. + +```java +import fr.neutronstars.nbot.command.CommandManager; + +public class MyPlugin extends NBotPlugin +{ + @Override + public void onEnable() + { + NBot.getLogger().log("MyPlugin is loaded."); + CommandManager.registerCommand(new MyCommand(), this); + } +} +``` + +To ensure that your plugin is **valid** you will also have to add a **plugin.json** at your root. + +```json +{ + "main":"packages.MainClass", + "name":"My Plugin", + "version":"0.0.1-SNAPSHOT" +} +``` + +Generate your `.jar` and put it in the **plugins** folder. \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..344baef --- /dev/null +++ b/build.gradle @@ -0,0 +1,14 @@ +group 'fr.neutronstars' +version '1.0.0' + +apply plugin: 'java' + +sourceCompatibility = 1.8 + +repositories { + jcenter() +} + +dependencies { + compile 'net.dv8tion:JDA:3.3.0_273' +} diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..4453cce --- /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..df35800 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'NBot' + diff --git a/src/main/java/fr/neutronstars/nbot/NBot.java b/src/main/java/fr/neutronstars/nbot/NBot.java new file mode 100644 index 0000000..4ac6249 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/NBot.java @@ -0,0 +1,89 @@ +package fr.neutronstars.nbot; + +import fr.neutronstars.nbot.entity.Console; +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.exception.NBotInitializationException; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.plugin.PluginManager; +import fr.neutronstars.nbot.util.Configuration; +import net.dv8tion.jda.core.JDA; + +import java.io.IOException; + +/** + * Created by NeutronStars on 30/07/2017 + */ +public final class NBot +{ + private static final String NAME = "NBot", VERSION = "2.0.0", AUTHOR = "NeutronStars"; + private static final NBotLogger logger = NBotLogger.getLogger("NBot"); + private static NBotServer server; + + protected static void setServer(NBotServer server) + { + if(NBot.server != null) throw new NBotInitializationException("The class NBotServer is already initialized."); + NBot.server = server; + } + + public static JDA getJDA() + { + return server.getJDA(); + } + + public static NBotLogger getLogger() + { + return logger; + } + + public static String getName() + { + return NAME; + } + + public static String getVersion() + { + return VERSION; + } + + public static String getAuthor() + { + return AUTHOR; + } + + public static Guild getGuild(net.dv8tion.jda.core.entities.Guild guild) + { + return server.getGuild(guild); + } + + public static Console getConsole() + { + return server.getConsole(); + } + + public static PluginManager getPluginManager() + { + return server.getPluginManager(); + } + + public static Configuration getConfiguration() + { + return server.getNBotConfiguration(); + } + + public static void saveLogger() + { + try + { + NBotLogger.save("logs", logger.nowTimeFormat().split("-")[0].replace("/", "-")); + } + catch(IOException e) + { + logger.logThrowable(e); + logger.log("Stopping NBot in 5 seconds."); + try + { + Thread.sleep(5000L); + }catch(Exception e1){} + } + } +} diff --git a/src/main/java/fr/neutronstars/nbot/NBotServer.java b/src/main/java/fr/neutronstars/nbot/NBotServer.java new file mode 100644 index 0000000..79587e6 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/NBotServer.java @@ -0,0 +1,75 @@ +package fr.neutronstars.nbot; + +import fr.neutronstars.nbot.command.CommandManager; +import fr.neutronstars.nbot.command.defaut.DefaultCommand; +import fr.neutronstars.nbot.entity.Console; +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.listener.NBotListener; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.plugin.PluginManager; +import fr.neutronstars.nbot.util.Configuration; +import net.dv8tion.jda.core.AccountType; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.JDABuilder; +import net.dv8tion.jda.core.exceptions.RateLimitedException; + +import javax.security.auth.login.LoginException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by NeutronStars on 30/07/2017 + */ +final class NBotServer +{ + private final NBotLogger logger = NBotLogger.getLogger("NBot"); + private final Map guilds = new HashMap<>(); + private final Configuration configuration; + private final PluginManager pluginManager; + private final JDA jda; + + private Console console; + + protected NBotServer(Configuration configuration, PluginManager pluginManager) throws LoginException, RateLimitedException + { + this.configuration = configuration; + this.pluginManager = pluginManager; + + CommandManager.registerCommand(new DefaultCommand(), null); + + jda = new JDABuilder(AccountType.BOT).setToken(configuration.getString("token")) + .addEventListener(new NBotListener(pluginManager)).buildAsync(); + } + + public JDA getJDA() + { + return jda; + } + + public PluginManager getPluginManager() + { + return pluginManager; + } + + public Configuration getNBotConfiguration() + { + return configuration; + } + + public Console getConsole() + { + if(console == null) console = new Console(pluginManager); + return console; + } + + public Guild getGuild(net.dv8tion.jda.core.entities.Guild guild) + { + if(!guilds.containsKey(guild.getIdLong())) + { + guilds.put(guild.getIdLong(), new Guild(guild)); + } + + return guilds.get(guild.getIdLong()); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/NBotStart.java b/src/main/java/fr/neutronstars/nbot/NBotStart.java new file mode 100644 index 0000000..6b95608 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/NBotStart.java @@ -0,0 +1,77 @@ +package fr.neutronstars.nbot; + +import fr.neutronstars.nbot.exception.NBotConfigurationException; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.plugin.PluginManager; +import fr.neutronstars.nbot.util.Configuration; + +import java.io.File; + +/** + * Created by NeutronStars on 30/07/2017 + */ +public class NBotStart +{ + private static final NBotLogger logger = NBotLogger.getLogger("NBot"); + + public static void main(String... args) + { + loadFolders("guilds", "plugins", "config"); + + Configuration configuration = loadConfiguration(); + setDefaultConfiguration(configuration); + + logger.log(String.format("Starting %1$s v%2$s by %3$s...", NBot.getName(), NBot.getVersion(), NBot.getAuthor())); + + PluginManager pluginManager = new PluginManager(configuration.getString("loadedFormat"), configuration.getString("enabledFormat"), configuration.getString("disabledFormat")); + + try + { + NBot.setServer(new NBotServer(configuration, pluginManager)); + } catch(Exception e) + { + logger.logThrowable(e); + NBot.saveLogger(); + } + } + + private static Configuration loadConfiguration() + { + return Configuration.loadConfiguration(new File("config/config.json")); + } + + private static void setDefaultConfiguration(Configuration configuration) + { + if(configuration == null) + { + logger.logThrowable(new NBotConfigurationException("The config cannot be null.")); + NBot.saveLogger(); + System.exit(0); + } + + if(!configuration.has("token")) configuration.set("token", "Insert your token here."); + + if(!configuration.has("dateFormat")) configuration.set("dateFormat", NBotLogger.getDateFormat()); + NBotLogger.setDateFormat(configuration.getString("dateFormat")); + + if(!configuration.has("pattern")) configuration.set("pattern", NBotLogger.getPattern()); + NBotLogger.setPattern(configuration.getString("pattern")); + + if(!configuration.has("playing")) configuration.set("playing", "null"); + + if(!configuration.has("loadedFormat")) configuration.set("loadedFormat", "%1$s v%2$s by %3$s is loaded."); + if(!configuration.has("enabledFormat")) configuration.set("enabledFormat", "%1$s v%2$s by %3$s is enabled."); + if(!configuration.has("disabledFormat")) configuration.set("disabledFormat", "%1$s v%2$s by %3$s is disabled."); + + configuration.save(); + } + + private static void loadFolders(String... names) + { + for(String name: names) + { + File file = new File(name); + if(!file.exists()) file.mkdir(); + } + } +} diff --git a/src/main/java/fr/neutronstars/nbot/command/Command.java b/src/main/java/fr/neutronstars/nbot/command/Command.java new file mode 100644 index 0000000..e68f9b1 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/command/Command.java @@ -0,0 +1,20 @@ +package fr.neutronstars.nbot.command; + +import java.lang.annotation.*; + +/** + * Created by NeutronStars on 02/08/2017 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Command +{ + String name(); + String description() default "hasn't description."; + + int powers() default 0; + + long[] guilds() default {}; + long[] channels() default {}; +} diff --git a/src/main/java/fr/neutronstars/nbot/command/CommandManager.java b/src/main/java/fr/neutronstars/nbot/command/CommandManager.java new file mode 100644 index 0000000..62deebb --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/command/CommandManager.java @@ -0,0 +1,45 @@ +package fr.neutronstars.nbot.command; + +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.plugin.NBotPlugin; + +import java.lang.reflect.Method; +import java.util.*; + +/** + * Created by NeutronStars on 21/09/2017 + */ +public class CommandManager +{ + private static final List defaultCommand = new ArrayList<>(); + + public static void registerCommands(NBotPlugin plugin, Object... objects) + { + for(Object object : objects) registerCommand(object, plugin); + } + + public static void registerCommand(Object commandManager, NBotPlugin plugin){ + for(Method method : commandManager.getClass().getDeclaredMethods()){ + if(method.isAnnotationPresent(Command.class)){ + Command command = method.getAnnotation(Command.class); + method.setAccessible(true); + SimpleCommand simpleCommand = new SimpleCommand(command.name(), command.description(), command.powers(), command.guilds(), command.channels(), method, commandManager, plugin); + defaultCommand.add(simpleCommand); + } + } + } + + protected static Map getCommandMap(Guild guild) + { + Map commandMap = new HashMap<>(); + + for(SimpleCommand simpleCommand : defaultCommand) + { + if(simpleCommand.getGuilds().size() != 0 && !simpleCommand.guildCanExecute(guild)) continue; + commandMap.put(simpleCommand.getSimpleName(), simpleCommand.clone(guild)); + } + + return commandMap; + } + +} diff --git a/src/main/java/fr/neutronstars/nbot/command/CommandMap.java b/src/main/java/fr/neutronstars/nbot/command/CommandMap.java new file mode 100644 index 0000000..20e6d35 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/command/CommandMap.java @@ -0,0 +1,169 @@ +package fr.neutronstars.nbot.command; + +import fr.neutronstars.nbot.NBot; +import fr.neutronstars.nbot.entity.*; +import fr.neutronstars.nbot.util.Configuration; +import net.dv8tion.jda.core.JDA; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by NeutronStars on 02/08/2017 + */ +public final class CommandMap +{ + private final List commands = new ArrayList<>(); + private final Map commandMap; + private final Configuration commandsDefaultConfig; + private String prefix = "bot."; + private final Guild guild; + + public CommandMap(Guild guild) + { + this.guild = guild; + commandsDefaultConfig = Configuration.loadConfiguration(new File(guild.getFolder(), "commands.json")); + + commandMap = CommandManager.getCommandMap(guild); + commands.addAll(commandMap.values()); + + if(guild.getConfiguration().has("prefix")) prefix = guild.getConfiguration().getString("prefix"); + + loadCommands(); + } + + private void loadCommands() + { + List objects = commandsDefaultConfig.getList("commands"); + for(JSONObject object : objects) + { + if(object.has("name")) + { + SimpleCommand command = commandMap.get(object.getString("name")); + if(command == null) continue; + + if(object.has("customName")) + { + String customName = object.getString("customName"); + if(!customName.equalsIgnoreCase("null")) setCustomNameCommand(command.getSimpleName(), customName.toLowerCase()); + } + + if(object.has("aliases")) + { + JSONArray array = object.getJSONArray("aliases"); + for(int i = 0; i < array.length(); i++) + { + String alias = array.getString(i).toLowerCase(); + if(alias.equalsIgnoreCase("")) continue; + if(!commandMap.containsKey(alias)) + { + command.addAlias(alias); + commandMap.put(alias, command); + } + } + } + + if(object.has("power")) command.setPower(object.getInt("power")); + } + } + } + + public Guild getGuild() + { + return guild; + } + + public String getPrefix() + { + return prefix; + } + + public void setPrefix(String prefix) + { + if(prefix == null) prefix = "bot."; + this.prefix = prefix; + guild.getConfiguration().set("prefix", prefix); + } + + public SimpleCommand getCommand(String name) + { + return commandMap.get(name); + } + + public boolean setCustomNameCommand(String lastName, String newName) + { + if(newName != null && commandMap.containsKey(newName)) return false; + SimpleCommand simpleCommand = commandMap.get(lastName); + if(simpleCommand == null) return false; + simpleCommand.setCustomName(newName); + commandMap.remove(lastName); + if(newName == null) commandMap.put(simpleCommand.getName(), simpleCommand); + else commandMap.put(newName, simpleCommand); + return true; + } + + public void save() + { + commandsDefaultConfig.clear(); + JSONArray array = new JSONArray(); + for(SimpleCommand command : commands) + array.put(new JSONObject(command.toString())); + commandsDefaultConfig.set("commands", array); + commandsDefaultConfig.save(); + } + + public boolean onCommand(User user, String command, Message message) + { + if(command == null) return false; + Object[] objects = getCommands(command.split(" ")); + if(objects[0] == null) return false; + + SimpleCommand simpleCommand = (SimpleCommand)objects[0]; + if(!guild.hasPermission(user, simpleCommand.getPower())) return false; + + try { + execute(simpleCommand, command, (String[]) objects[1], message, user); + }catch(Exception e) { + NBot.getLogger().logThrowable(e); + } + return true; + } + + public Object[] getCommands(String[] commandSplit) + { + if(commandSplit.length == 0) return null; + String label = commandSplit[0].toLowerCase(); + String[] args = new String[commandSplit.length-1]; + for(int i = 1; i < commandSplit.length; i++) args[i-1] = commandSplit[i]; + return new Object[]{commandMap.get(label), args}; + } + + public List getCommands() + { + return new ArrayList<>(commands); + } + + private void execute(SimpleCommand simpleCommand, String command, String[] args, Message message, User user) throws Exception{ + Parameter[] parameters = simpleCommand.getMethod().getParameters(); + Object[] objects = new Object[parameters.length]; + for(int i = 0; i < parameters.length; i++){ + if(parameters[i].getType() == JDA.class) objects[i] = NBot.getJDA(); + else if(parameters[i].getType() == String[].class) objects[i] = args; + else if(parameters[i].getType() == String.class) objects[i] = command; + else if(parameters[i].getType() == Message.class) objects[i] = message; + else if(parameters[i].getType() == Guild.class) objects[i] = message == null ? null : NBot.getGuild(message.getGuild()); + else if(parameters[i].getType() == Channel.class) objects[i] = message == null ? null : message.getMessageChannel(); + + else if(parameters[i].getType() == User.class) objects[i] = user; + else if(parameters[i].getType() == CommandSender.class) objects[i] = user; + else if(parameters[i].getType() == SimpleCommand.class) objects[i] = simpleCommand; + } + + simpleCommand.getMethod().invoke(simpleCommand.getObject(), objects); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/command/SimpleCommand.java b/src/main/java/fr/neutronstars/nbot/command/SimpleCommand.java new file mode 100644 index 0000000..6766c1f --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/command/SimpleCommand.java @@ -0,0 +1,170 @@ +package fr.neutronstars.nbot.command; + +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.plugin.NBotPlugin; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Created by NeutronStars on 02/08/2017 + */ +public class SimpleCommand +{ + private final String name, description; + private final List guilds = new ArrayList<>(), channels = new ArrayList<>(); + private final List aliases = new ArrayList<>(); + private final NBotPlugin plugin; + private final Method method; + private final Object object; + + private String customName; + private int power; + + protected SimpleCommand(String name, String description, int power, List guilds, List channels, Method method, Object object, NBotPlugin plugin) + { + this.name = name.toLowerCase(); + this.description = description; + this.power = power; + this.guilds.addAll(guilds); + this.channels.addAll(channels); + this.method = method; + this.object = object; + this.plugin = plugin; + } + + protected SimpleCommand(String name, String description, int power, long[] guilds, long[] channels, Method method, Object object, NBotPlugin plugin) + { + this.name = name.toLowerCase(); + this.description = description; + this.power = power; + for(long l : guilds) this.guilds.add(l); + for(long l : channels) this.channels.add(l); + this.method = method; + this.object = object; + this.plugin = plugin; + } + + public String getName() + { + return name; + } + + public String getDescription() + { + return description; + } + + public List getChannels() + { + return channels; + } + + public List getGuilds() + { + return guilds; + } + + public int getPower() + { + return power; + } + + public Method getMethod() + { + return method; + } + + public Object getObject() + { + return object; + } + + public NBotPlugin getPlugin() + { + return plugin; + } + + public String getCustomName() + { + return customName; + } + + public List getAliases() + { + return aliases; + } + + public String getSimpleName() + { + return customName == null ? name : customName; + } + + public boolean guildCanExecute(Guild guild) + { + return guilds.contains(guild.getIdLong()); + } + + public void setCustomName(String customName) + { + this.customName = customName; + } + + public void setPower(int power) + { + this.power = power; + } + + public void addAlias(String... aliases) + { + for(String alias : aliases) + if(!this.aliases.contains(alias)) this.aliases.add(alias); + } + + public void addAlias(Collection aliases) + { + for(String alias : aliases) + if(!this.aliases.contains(alias)) this.aliases.add(alias); + } + + public String getAliasesToString() + { + StringBuilder builder = new StringBuilder(); + + for(String alias : aliases) + { + if(builder.length() > 0) builder.append(", "); + builder.append(alias); + } + + return builder.length() == 0 ? "Not Alias" : builder.toString(); + } + + public void removeAlias(String... aliases) + { + for(String alias : aliases) + if(!this.aliases.contains(alias)) this.aliases.remove(alias); + } + + public SimpleCommand clone(Guild guild) + { + return new SimpleCommand(name, description, power, Arrays.asList(guild.getIdLong()), new ArrayList<>(channels), method, object, plugin); + } + + public String toString() + { + return new StringBuilder() + .append("{\"name\":\"").append(name) + .append("\",\"customName\":\"").append(customName) + .append("\",\"description\":\"").append(description) + .append("\",\"power\":").append(power) + .append(",\"guilds\":").append(guilds.toString()) + .append(",\"channels\":").append(channels.toString()) + .append(",\"aliases\":") + .append(aliases.toString().replace(" ", "").replace("[", "[\"").replace(",", "\",\"").replace("]", "\"]")) + .append("}").toString(); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/command/defaut/DefaultCommand.java b/src/main/java/fr/neutronstars/nbot/command/defaut/DefaultCommand.java new file mode 100644 index 0000000..c70242b --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/command/defaut/DefaultCommand.java @@ -0,0 +1,119 @@ +package fr.neutronstars.nbot.command.defaut; + +import fr.neutronstars.nbot.NBot; +import fr.neutronstars.nbot.command.Command; +import fr.neutronstars.nbot.command.SimpleCommand; +import fr.neutronstars.nbot.entity.Channel; +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.entity.Message; +import fr.neutronstars.nbot.entity.User; +import fr.neutronstars.nbot.plugin.NBotPlugin; +import net.dv8tion.jda.core.EmbedBuilder; +import net.dv8tion.jda.core.entities.Role; + +import java.awt.*; +import java.util.Collection; +import java.util.List; + +/** + * Created by NeutronStars on 21/09/2017 + */ +public class DefaultCommand +{ + @Command(name = "help") + private void onHelp(User user, Channel channel, Guild guild) + { + Collection commands = guild.getCommands(); + EmbedBuilder builder = new EmbedBuilder(); + builder.setTitle("Commands List"); + builder.setDescription("Commands for the guild "+guild.getName()+"\n -> Prefix : "+guild.getPrefix()); + builder.setColor(Color.MAGENTA); + builder.setFooter("API "+NBot.getName()+" v"+NBot.getVersion()+" by "+NBot.getAuthor(), null); + + for(SimpleCommand command : commands) + { + if(!guild.hasPermission(user, command.getPower())) continue; + String value = "[>](1) Description : "+command.getDescription(); + if(command.getAliases().size() > 0) value += "\n[>](2) Aliases : "+command.getAliasesToString(); + builder.addField(command.getName(), value, false); + } + + user.sendMessageToChannel(builder.build()); + channel.sendMessageToChannel(user.getAsMention()+" check your private message !"); + } + + @Command(name="plugins") + private void onPlugins(Channel channel) + { + Collection plugins = NBot.getPluginManager().getPlugins(); + if(plugins.size() == 0) + { + channel.sendMessageToChannel("There is no plugin."); + return; + } + EmbedBuilder builder = new EmbedBuilder(); + + builder.setTitle("Plugins list"); + builder.setColor(Color.RED); + builder.setFooter("API "+NBot.getName()+" v"+NBot.getVersion()+" by "+NBot.getAuthor(), null); + + for(NBotPlugin plugin : plugins) + builder.addField(plugin.getName(), "[>](1) Version : "+plugin.getVersion()+"\n[>](2) Author(s) : "+plugin.getAuthorsToString(), true); + + channel.sendMessageToChannel(builder.build()); + } + + @Command(name = "prefix", powers = 100) + private void onPrefix(Guild guild, Channel channel, String[] args) + { + String prefix = args.length == 0 || args[0].equalsIgnoreCase("null") ? null : args[0]; + guild.setPrefix(prefix); + channel.sendMessageToChannel("Prefix modified -> "+prefix); + } + + @Command(name="power", powers = 100) + private void onPower(SimpleCommand command, Message message, String[] args, Guild guild) + { + if(args.length < 2) + { + message.getMessageChannel().sendMessageToChannel(command.getSimpleName()+" "); + return; + } + + int powers = 0; + try { + powers = Integer.parseInt(args[0]); + }catch(NumberFormatException nfe){ + message.getMessageChannel().sendMessageToChannel(command.getSimpleName()+" "); + return; + } + + if(message.getMentionedUsers().size() == 0 && message.getMentionedRoles().size() == 0) + { + SimpleCommand simpleCommand = guild.getCommand(args[1]); + if(simpleCommand == null) message.getMessageChannel().sendMessageToChannel(command.getSimpleName()+" "); + else + { + simpleCommand.setPower(powers); + message.getMessageChannel().sendMessageToChannel("Power modified for the command "+args[2]); + } + return; + } + + StringBuilder builder = new StringBuilder("Permission added ->"); + + for(net.dv8tion.jda.core.entities.User user : message.getMentionedUsers()) + { + guild.setPermission(user, powers); + builder.append(" ").append(user.getAsMention()); + } + + for(Role role : message.getMentionedRoles()) + { + guild.setPermission(role, powers); + builder.append(" ").append(role.getAsMention()); + } + + message.getMessageChannel().sendMessageToChannel(builder.toString()); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/Channel.java b/src/main/java/fr/neutronstars/nbot/entity/Channel.java new file mode 100644 index 0000000..2a873fc --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/Channel.java @@ -0,0 +1,245 @@ +package fr.neutronstars.nbot.entity; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Message; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.entities.impl.UserImpl; +import net.dv8tion.jda.core.requests.RestAction; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by NeutronStars on 19/07/2017 + */ +public class Channel implements MessageChannel +{ + private final MessageChannel messageChannel; + + public Channel(MessageChannel messageChannel) + { + this.messageChannel = messageChannel; + } + + protected Channel(User user) + { + if(!user.hasPrivateChannel()) user.openPrivateChannel().complete(); + messageChannel = ((UserImpl)user).getPrivateChannel(); + } + + public MessageChannel getMessageChannel() + { + return messageChannel; + } + + public long getLatestMessageIdLong() + { + return messageChannel.getLatestMessageIdLong(); + } + + public boolean hasLatestMessage() + { + return messageChannel.hasLatestMessage(); + } + + public String getName() + { + return messageChannel.getName(); + } + + public ChannelType getType() + { + return messageChannel.getType(); + } + + public JDA getJDA() + { + return messageChannel.getJDA(); + } + + public long getIdLong() + { + return messageChannel.getIdLong(); + } + + public RestAction sendMessage(String text) + { + return messageChannel.sendMessage(text); + } + + public RestAction sendMessage(Message msg) + { + return messageChannel.sendMessage(msg); + } + + public RestAction sendMessageFormat(String format, Object... args) + { + return messageChannel.sendMessageFormat(format, args); + } + + public void sendMessageToChannel(String message) + { + messageChannel.sendMessage(message).queue(); + } + + public void sendMessageToChannel(net.dv8tion.jda.core.entities.Message message) + { + messageChannel.sendMessage(message).queue(); + } + + public void sendMessageToChannel(MessageEmbed embed) + { + messageChannel.sendMessage(embed).queue(); + } + + public void sendMessageFormatToChannel(String format, Object... args) + { + sendMessageToChannel(String.format(format, args)); + } + + public void sendFileToChannel(File file, Message message) + { + messageChannel.sendFile(file, message).queue(); + } + + public void sendFileToChannel(File file, String fileName, Message message) + { + messageChannel.sendFile(file, fileName, message).queue(); + } + + public void sendFileToChannel(InputStream data, String fileName, Message message) + { + messageChannel.sendFile(data, fileName, message).queue(); + } + + public void sendFileToChannel(byte[] data, String fileName, Message message) + { + messageChannel.sendFile(data, fileName, message).queue(); + } + + public fr.neutronstars.nbot.entity.Message getMessageByIdToChannel(String messageId) + { + return new fr.neutronstars.nbot.entity.Message(getMessageById(messageId).complete()); + } + + public fr.neutronstars.nbot.entity.Message getMessageByIdToChannel(long messageId) + { + return new fr.neutronstars.nbot.entity.Message(getMessageById(messageId).complete()); + } + + public void deleteMessageByIdToChannel(String messageId) + { + messageChannel.deleteMessageById(messageId).queue(); + } + + public void deleteMessageByIdToChannel(long messageId) + { + messageChannel.deleteMessageById(messageId).queue(); + } + + public MessageHistory getHistoryAroundToChannel(Message message, int limit) + { + return messageChannel.getHistoryAround(message, limit).complete(); + } + + public MessageHistory getHistoryAroundToChannel(String messageId, int limit) + { + return messageChannel.getHistoryAround(messageId, limit).complete(); + } + + public MessageHistory getHistoryAroundToChannel(long messageId, int limit) + { + return messageChannel.getHistoryAround(messageId, limit).complete(); + } + + public void sendTypingToChannel() + { + messageChannel.sendTyping().complete(); + } + + public void addReactionByIdToChannel(String messageId, String unicode) + { + messageChannel.addReactionById(messageId, unicode).queue(); + } + + public void addReactionByIdToChannel(long messageId, String unicode) + { + messageChannel.addReactionById(messageId, unicode).queue(); + } + + public void addReactionByIdToChannel(String messageId, Emote emote) + { + messageChannel.addReactionById(messageId, emote).queue(); + } + + public void addReactionByIdToChannel(long messageId, Emote emote) + { + messageChannel.addReactionById(messageId, emote).queue(); + } + + public void pinMessageByIdToChannel(String messageId) + { + pinMessageById(messageId).complete(); + } + + public void pinMessageByIdToChannel(long messageId) + { + messageChannel.pinMessageById(messageId).complete(); + } + + public void unpinMessageByIdToChannel(String messageId) + { + messageChannel.unpinMessageById(messageId).complete(); + } + + public void unpinMessageByIdToChannel(long messageId) + { + messageChannel.unpinMessageById(messageId).complete(); + } + + public List getPinnedMessagesToChannel() + { + List messages = new ArrayList<>(); + for(Message message : messageChannel.getPinnedMessages().complete()) messages.add(new fr.neutronstars.nbot.entity.Message(message)); + return messages; + } + + public fr.neutronstars.nbot.entity.Message editMessageByIdToChannel(String messageId, String newContent) + { + return new fr.neutronstars.nbot.entity.Message(editMessageById(messageId, newContent).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageByIdToChannel(String messageId, Message newContent) + { + return new fr.neutronstars.nbot.entity.Message(editMessageById(messageId, newContent).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageFormatByIdToChannel(String messageId, String format, Object... args) + { + return new fr.neutronstars.nbot.entity.Message(editMessageFormatById(messageId, format, args).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageFormatByIdToChannel(long messageId, String format, Object... args) + { + return new fr.neutronstars.nbot.entity.Message(editMessageFormatById(messageId, format, args).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageByIdToChannel(long messageId, Message newContent) + { + return new fr.neutronstars.nbot.entity.Message(editMessageById(messageId, newContent).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageByIdToChannel(String messageId, MessageEmbed newContent) + { + return new fr.neutronstars.nbot.entity.Message(editMessageById(messageId, newContent).complete()); + } + + public fr.neutronstars.nbot.entity.Message editMessageByIdToChannel(long messageId, MessageEmbed newContent) + { + return new fr.neutronstars.nbot.entity.Message(editMessageById(messageId, newContent).complete()); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/CommandSender.java b/src/main/java/fr/neutronstars/nbot/entity/CommandSender.java new file mode 100644 index 0000000..7dfdbcf --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/CommandSender.java @@ -0,0 +1,33 @@ +package fr.neutronstars.nbot.entity; + +import fr.neutronstars.nbot.NBot; +import net.dv8tion.jda.core.JDA; + +/** + * Created by NeutronStars on 20/07/2017 + */ +public interface CommandSender +{ + public void sendMessageToSender(String message); + + public String getName(); + + public void performCommand(String command); + + public default JDA getJDA() + { + return NBot.getJDA(); + } + + public String getAsMention(); + + public default boolean isConsole() + { + return false; + } + + public default boolean isUser() + { + return false; + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/Console.java b/src/main/java/fr/neutronstars/nbot/entity/Console.java new file mode 100644 index 0000000..1ea572f --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/Console.java @@ -0,0 +1,73 @@ +package fr.neutronstars.nbot.entity; + +import fr.neutronstars.nbot.NBot; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.plugin.PluginManager; +import net.dv8tion.jda.core.entities.*; + +import java.util.Scanner; + +/** + * Created by NeutronStars on 19/07/2017 + */ +public class Console implements CommandSender, Runnable +{ + private final NBotLogger logger = NBotLogger.getLogger("NBot"); + private final Thread thread = new Thread(this, "console"); + private final Scanner scanner = new Scanner(System.in); + private final PluginManager pluginManager; + + public Console(PluginManager pluginManager){ + this.pluginManager = pluginManager; + thread.start(); + } + + public String getName() + { + return "Server"; + } + + public void performCommand(String command) + { + + } + + public void run() + { + while(true) + { + if(scanner.hasNextLine()) + { + if(scanner.nextLine().equalsIgnoreCase("stop")) + { + break; + } + } + } + + pluginManager.disablePlugins(); + + for(net.dv8tion.jda.core.entities.Guild guild : NBot.getJDA().getGuilds()) + NBot.getGuild(guild).save(); + + NBot.getJDA().shutdown(); + logger.log(NBot.getName()+ " is down."); + NBot.saveLogger(); + System.exit(0); + } + + public void sendMessageToSender(String message) + { + logger.log(message); + } + + public String getAsMention() + { + return getName(); + } + + public boolean isConsole() + { + return true; + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/Guild.java b/src/main/java/fr/neutronstars/nbot/entity/Guild.java new file mode 100644 index 0000000..8d3a71f --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/Guild.java @@ -0,0 +1,514 @@ +package fr.neutronstars.nbot.entity; + +import fr.neutronstars.nbot.NBot; +import fr.neutronstars.nbot.command.CommandMap; +import fr.neutronstars.nbot.command.SimpleCommand; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.util.Configuration; +import fr.neutronstars.nbot.util.JSONReader; +import fr.neutronstars.nbot.util.JSONWriter; +import net.dv8tion.jda.client.requests.restaction.pagination.MentionPaginationAction; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.Permission; +import net.dv8tion.jda.core.Region; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.managers.AudioManager; +import net.dv8tion.jda.core.managers.GuildController; +import net.dv8tion.jda.core.managers.GuildManager; +import net.dv8tion.jda.core.managers.GuildManagerUpdatable; +import net.dv8tion.jda.core.requests.RestAction; +import net.dv8tion.jda.core.requests.restaction.pagination.AuditLogPaginationAction; +import net.dv8tion.jda.core.utils.cache.MemberCacheView; +import net.dv8tion.jda.core.utils.cache.SnowflakeCacheView; +import org.json.JSONObject; + +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by NeutronStars on 19/07/2017 + */ +public class Guild implements net.dv8tion.jda.core.entities.Guild +{ + private final net.dv8tion.jda.core.entities.Guild guild; + private final CommandMap commandMap; + private final Map usersPower; + private final Map rolePowers; + private final Configuration configuration; + + private final File folder; + + public Guild(net.dv8tion.jda.core.entities.Guild guild) + { + if(guild == null) throw new NullPointerException("The guild cannot be null."); + this.guild = guild; + + folder = new File("guilds/"+guild.getId()); + if(!folder.exists()) folder.mkdir(); + + configuration = Configuration.loadConfiguration(new File(folder, "config.json")); + + File file = new File(folder, "users.json"); + if(file.exists()) usersPower = JSONReader.toMap(file); + else usersPower = new HashMap<>(); + + File powersRole = new File(folder, "powersRole.json"); + if(powersRole.exists()) this.rolePowers = JSONReader.toMap(powersRole); + else this.rolePowers = new HashMap<>(); + + commandMap = new CommandMap(this); + } + + public net.dv8tion.jda.core.entities.Guild getGuild() + { + return guild; + } + + public String getName() + { + return guild.getName(); + } + + public String getIconId() + { + return guild.getIconId(); + } + + public String getIconUrl() + { + return guild.getIconUrl(); + } + + public String getSplashId() + { + return guild.getSplashId(); + } + + public String getSplashUrl() + { + return guild.getSplashUrl(); + } + + public VoiceChannel getAfkChannel() + { + return guild.getAfkChannel(); + } + + public TextChannel getSystemChannel() + { + return guild.getSystemChannel(); + } + + public Member getOwner() + { + return guild.getOwner(); + } + + public Timeout getAfkTimeout() + { + return guild.getAfkTimeout(); + } + + public Region getRegion() + { + return guild.getRegion(); + } + + public boolean isMember(User user) + { + return guild.isMember(user); + } + + public Member getSelfMember() + { + return guild.getSelfMember(); + } + + public Member getMember(User user) + { + return guild.getMember(user); + } + + public Member getMemberById(String s) + { + return guild.getMemberById(s); + } + + public Member getMemberById(long l) + { + return guild.getMemberById(l); + } + + public List getMembers() + { + return guild.getMembers(); + } + + public List getMembersByName(String s, boolean b) + { + return guild.getMembersByName(s,b); + } + + public List getMembersByNickname(String s, boolean b) + { + return guild.getMembersByNickname(s, b); + } + + public List getMembersByEffectiveName(String s, boolean b) + { + return guild.getMembersByEffectiveName(s, b); + } + + public List getMembersWithRoles(Role... roles) + { + return guild.getMembersWithRoles(roles); + } + + public List getMembersWithRoles(Collection collection) + { + return guild.getMembersWithRoles(collection); + } + + public MemberCacheView getMemberCache() + { + return guild.getMemberCache(); + } + + public SnowflakeCacheView getCategoryCache() + { + return guild.getCategoryCache(); + } + + public TextChannel getTextChannelById(String s) + { + return guild.getTextChannelById(s); + } + + public TextChannel getTextChannelById(long l) + { + return guild.getTextChannelById(l); + } + + public List getTextChannels() + { + return guild.getTextChannels(); + } + + public List getTextChannelsByName(String s, boolean b) + { + return guild.getTextChannelsByName(s, b); + } + + public SnowflakeCacheView getTextChannelCache() + { + return guild.getTextChannelCache(); + } + + public VoiceChannel getVoiceChannelById(String s) + { + return guild.getVoiceChannelById(s); + } + + public VoiceChannel getVoiceChannelById(long l) + { + return guild.getVoiceChannelById(l); + } + + public List getVoiceChannels() + { + return guild.getVoiceChannels(); + } + + public List getVoiceChannelsByName(String s, boolean b) + { + return guild.getVoiceChannelsByName(s, b); + } + + public SnowflakeCacheView getVoiceChannelCache() + { + return guild.getVoiceChannelCache(); + } + + public Role getRoleById(String s) + { + return guild.getRoleById(s); + } + + public Role getRoleById(long l) + { + return guild.getRoleById(l); + } + + public List getRoles() + { + return guild.getRoles(); + } + + public List getRolesByName(String s, boolean b) + { + return guild.getRolesByName(s, b); + } + + public SnowflakeCacheView getRoleCache() + { + return guild.getRoleCache(); + } + + public Emote getEmoteById(String s) + { + return guild.getEmoteById(s); + } + + public Emote getEmoteById(long l) + { + return guild.getEmoteById(l); + } + + public List getEmotes() + { + return guild.getEmotes(); + } + + public List getEmotesByName(String s, boolean b) + { + return guild.getEmotesByName(s, b); + } + + public SnowflakeCacheView getEmoteCache() + { + return guild.getEmoteCache(); + } + + public RestAction> getBans() + { + return guild.getBans(); + } + + public RestAction getPrunableMemberCount(int i) + { + return guild.getPrunableMemberCount(i); + } + + public Role getPublicRole() + { + return guild.getPublicRole(); + } + + @Deprecated + public TextChannel getPublicChannel() + { + return guild.getPublicChannel(); + } + + @Nullable + public TextChannel getDefaultChannel() + { + return guild.getDefaultChannel(); + } + + public GuildManager getManager() + { + return guild.getManager(); + } + + public GuildManagerUpdatable getManagerUpdatable() + { + return guild.getManagerUpdatable(); + } + + public GuildController getController() + { + return guild.getController(); + } + + public MentionPaginationAction getRecentMentions() + { + return guild.getRecentMentions(); + } + + public AuditLogPaginationAction getAuditLogs() + { + return guild.getAuditLogs(); + } + + public RestAction leave() + { + return guild.leave(); + } + + public RestAction delete() + { + return guild.delete(); + } + + public RestAction delete(String s) + { + return guild.delete(s); + } + + public AudioManager getAudioManager() + { + return guild.getAudioManager(); + } + + public JDA getJDA() + { + return guild.getJDA(); + } + + public RestAction> getInvites() + { + return guild.getInvites(); + } + + public RestAction> getWebhooks() + { + return guild.getWebhooks(); + } + + public List getVoiceStates() + { + return guild.getVoiceStates(); + } + + public VerificationLevel getVerificationLevel() + { + return guild.getVerificationLevel(); + } + + public NotificationLevel getDefaultNotificationLevel() + { + return guild.getDefaultNotificationLevel(); + } + + public MFALevel getRequiredMFALevel() + { + return guild.getRequiredMFALevel(); + } + + public ExplicitContentLevel getExplicitContentLevel() + { + return guild.getExplicitContentLevel(); + } + + public boolean checkVerification() + { + return guild.checkVerification(); + } + + public boolean isAvailable() + { + return guild.isAvailable(); + } + + public long getIdLong() + { + return guild.getIdLong(); + } + + public File getFolder() + { + return folder; + } + + public Configuration getConfiguration() + { + return configuration; + } + + public int getPermissionUser(User user) + { + if(!usersPower.containsKey(user.getId())) setPermission(user, 0); + return usersPower.get(user.getId()); + } + + public void setPermission(User user, int power) + { + usersPower.put(user.getId(), power); + } + + public int getPermissionRole(Role role) + { + if(!rolePowers.containsKey(role.getId())) setPermission(role, 0); + return rolePowers.get(role.getId()); + } + + public void setPermission(Role role, int power) + { + rolePowers.put(role.getId(), power); + } + + public boolean hasPermission(fr.neutronstars.nbot.entity.User user, int power) + { + return hasPermission(user.getUser(), power); + } + + public boolean hasPermission(User user, int power) + { + if(guild.getOwner().equals(getMember(user))) return true; + if(getPermissionUser(user) >= power) return true; + + for(Role role : getMember(user).getRoles()) + if(role.hasPermission(Permission.ADMINISTRATOR) || getPermissionRole(role) >= power) return true; + + return false; + } + + public String getPrefix() + { + return commandMap.getPrefix(); + } + + public void save() + { + configuration.save(); + commandMap.save(); + + try(JSONWriter writer = new JSONWriter("guilds/"+guild.getId()+"/users.json"); + JSONWriter powerRoles = new JSONWriter("guilds/"+guild.getId()+"/powersRole.json")) + { + save(usersPower, writer); + save(rolePowers, powerRoles); + + NBot.getLogger().log(getName()+" is saved."); + } + catch(IOException ioe) + { + NBotLogger.getLogger("NBot").logThrowable(ioe); + } + } + + public SimpleCommand getCommand(String name) + { + return commandMap.getCommand(name); + } + + public Collection getCommands() + { + return commandMap.getCommands(); + } + + public void setPrefix(String newPrefix) + { + commandMap.setPrefix(newPrefix); + } + + public boolean executeCommand(fr.neutronstars.nbot.entity.User user, String command, Message message) + { + return commandMap.onCommand(user, command, message); + } + + private void save(Map map, JSONWriter writer) throws IOException + { + JSONObject object = new JSONObject(); + for(String key : map.keySet()) object.put(key, map.get(key)); + writer.write(object); + writer.flush(); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/Message.java b/src/main/java/fr/neutronstars/nbot/entity/Message.java new file mode 100644 index 0000000..895e49a --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/Message.java @@ -0,0 +1,308 @@ +package fr.neutronstars.nbot.entity; + +import net.dv8tion.jda.client.entities.Group; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.requests.RestAction; +import net.dv8tion.jda.core.requests.restaction.AuditableRestAction; + +import java.time.OffsetDateTime; +import java.util.Formatter; +import java.util.List; + +/** + * Created by NeutronStars on 20/07/2017 + */ +public class Message implements net.dv8tion.jda.core.entities.Message +{ + private final net.dv8tion.jda.core.entities.Message message; + private boolean deleted; + + public Message(net.dv8tion.jda.core.entities.Message message) + { + this.message = message; + } + + public net.dv8tion.jda.core.entities.Message getMessage() + { + return message; + } + + public List getMentionedUsers() + { + return message.getMentionedUsers(); + } + + public boolean isMentioned(User user) + { + return message.isMentioned(user); + } + + public List getMentionedChannels() + { + return message.getMentionedChannels(); + } + + public List getMentionedRoles() + { + return message.getMentionedRoles(); + } + + public boolean mentionsEveryone() + { + return message.mentionsEveryone(); + } + + public boolean isEdited() + { + return message.isEdited(); + } + + public OffsetDateTime getEditedTime() + { + return message.getEditedTime(); + } + + public User getAuthor() + { + return message.getAuthor(); + } + + public Member getMember() + { + return message.getMember(); + } + + public String getContent() + { + return message.getContent(); + } + + public String getRawContent() + { + return message.getContent(); + } + + public String getStrippedContent() + { + return message.getStrippedContent(); + } + + public boolean isFromType(ChannelType channelType) + { + return message.isFromType(channelType); + } + + public ChannelType getChannelType() + { + return message.getChannelType(); + } + + public boolean isWebhookMessage() + { + return message.isWebhookMessage(); + } + + public MessageChannel getChannel() + { + return message.getChannel(); + } + + public Channel getMessageChannel() + { + return new Channel(getChannel()); + } + + public PrivateChannel getPrivateChannel() + { + return message.getPrivateChannel(); + } + + public Group getGroup() + { + return message.getGroup(); + } + + public TextChannel getTextChannel() + { + return message.getTextChannel(); + } + + public Category getCategory() + { + return message.getCategory(); + } + + public Guild getGuild() + { + return message.getGuild(); + } + + public List getAttachments() + { + return message.getAttachments(); + } + + public List getEmbeds() + { + return message.getEmbeds(); + } + + public List getEmotes() + { + return message.getEmotes(); + } + + public List getReactions() + { + return message.getReactions(); + } + + public boolean isTTS() + { + return message.isTTS(); + } + + public RestAction editMessage(String s) + { + return message.editMessage(s); + } + + public void editTheMessage(String s) + { + editMessage(s).complete(); + } + + public RestAction editMessage(MessageEmbed messageEmbed) + { + return message.editMessage(messageEmbed); + } + + public void editTheMessage(MessageEmbed messageEmbed) + { + editMessage(messageEmbed).complete(); + } + + public RestAction editMessageFormat(String s, Object... objects) + { + return message.editMessageFormat(s, objects); + } + + public void editTheMessageFormat(String s, Object... objects) + { + editMessageFormat(s, objects).complete(); + } + + public RestAction editMessage(net.dv8tion.jda.core.entities.Message message) + { + return this.message.editMessage(message); + } + + public void editTheMessage(net.dv8tion.jda.core.entities.Message message) + { + editMessage(message).complete(); + } + + public AuditableRestAction delete() + { + deleted = true; + return message.delete(); + } + + public void deleteTheMessage() + { + delete().queue(); + } + + public JDA getJDA() + { + return message.getJDA(); + } + + public boolean isPinned() + { + return message.isPinned(); + } + + public RestAction pin() + { + return message.pin(); + } + + public void pinTheMessage() + { + pin().complete(); + } + + public RestAction unpin() + { + return message.unpin(); + } + + public void unpinTheMessage() + { + unpin().complete(); + } + + public RestAction addReaction(Emote emote) + { + return message.addReaction(emote); + } + + public void addReactionToMessage(Emote emote) + { + addReaction(emote).queue(); + } + + public void addReactionsToMessage(Emote... emotes) + { + for(Emote emote : emotes) addReaction(emote).queue(); + } + + public RestAction addReaction(String s) + { + return message.addReaction(s); + } + + public void addReactionToMessage(String s) + { + addReaction(s).queue(); + } + + public void addReactionsToMessage(String... ss) + { + for(String s : ss) addReaction(s).queue(); + } + + public RestAction clearReactions() + { + return message.clearReactions(); + } + + public void clearReactionsToMessage() + { + clearReactions().queue(); + } + + public MessageType getType() + { + return message.getType(); + } + + public void formatTo(Formatter formatter, int flags, int width, int precision) + { + message.formatTo(formatter, flags, width, precision); + } + + public long getIdLong() + { + return message.getIdLong(); + } + + public boolean isDeleted() + { + return deleted; + } +} diff --git a/src/main/java/fr/neutronstars/nbot/entity/User.java b/src/main/java/fr/neutronstars/nbot/entity/User.java new file mode 100644 index 0000000..6382a11 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/entity/User.java @@ -0,0 +1,137 @@ +package fr.neutronstars.nbot.entity; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.PrivateChannel; +import net.dv8tion.jda.core.requests.RestAction; +import net.dv8tion.jda.core.utils.MiscUtil; + +import java.util.Formatter; +import java.util.List; + +/** + * Created by NeutronStars on 19/07/2017 + */ +public class User extends Channel implements net.dv8tion.jda.core.entities.User, CommandSender +{ + private final net.dv8tion.jda.core.entities.User user; + + public User (net.dv8tion.jda.core.entities.User user) + { + super(user); + this.user = user; + } + + public net.dv8tion.jda.core.entities.User getUser() + { + return user; + } + + public String getName() + { + return user.getName(); + } + + public String getDiscriminator() + { + return user.getDiscriminator(); + } + + public String getAvatarId() + { + return user.getAvatarId(); + } + + public String getAvatarUrl() + { + return user.getAvatarUrl(); + } + + public String getDefaultAvatarId() + { + return user.getDefaultAvatarId(); + } + + public String getDefaultAvatarUrl() + { + return user.getDefaultAvatarUrl(); + } + + public String getEffectiveAvatarUrl() + { + return user.getEffectiveAvatarUrl(); + } + + public boolean hasPrivateChannel() + { + return user.hasPrivateChannel(); + } + + public RestAction openPrivateChannel() + { + return user.openPrivateChannel(); + } + + public List getMutualGuilds() + { + return user.getMutualGuilds(); + } + + public boolean isBot() + { + return user.isBot(); + } + + public JDA getJDA() + { + return user.getJDA(); + } + + public boolean isFake() + { + return user.isFake(); + } + + public String getAsMention() + { + return user.getAsMention(); + } + + public long getIdLong() + { + return user.getIdLong(); + } + + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean leftJustified = (flags & 1) == 1; + boolean upper = (flags & 2) == 2; + String out = upper?this.getAsMention().toUpperCase(formatter.locale()):this.getAsMention(); + MiscUtil.appendTo(formatter, width, precision, leftJustified, out); + } + + public void sendMessageToSender(String message) + { + sendMessageToChannel(message); + } + + public void performCommand(String command) + { + + } + + public boolean isUser() + { + return true; + } + + public String toString() + { + return user.toString(); + } + + public boolean equals(Object obj) + { + if(obj instanceof User) obj = ((User)obj).getUser(); + return user.equals(obj); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/exception/NBotConfigurationException.java b/src/main/java/fr/neutronstars/nbot/exception/NBotConfigurationException.java new file mode 100644 index 0000000..1cd45d6 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/exception/NBotConfigurationException.java @@ -0,0 +1,27 @@ +package fr.neutronstars.nbot.exception; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public class NBotConfigurationException extends NBotException +{ + public NBotConfigurationException() + { + super(); + } + + public NBotConfigurationException(String message) + { + super(message); + } + + public NBotConfigurationException(Throwable cause) + { + super(cause); + } + + public NBotConfigurationException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/exception/NBotException.java b/src/main/java/fr/neutronstars/nbot/exception/NBotException.java new file mode 100644 index 0000000..c4136b6 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/exception/NBotException.java @@ -0,0 +1,27 @@ +package fr.neutronstars.nbot.exception; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public abstract class NBotException extends RuntimeException +{ + public NBotException() + { + super(); + } + + public NBotException(String message) + { + super(message); + } + + public NBotException(Throwable cause) + { + super(cause); + } + + public NBotException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/exception/NBotInitializationException.java b/src/main/java/fr/neutronstars/nbot/exception/NBotInitializationException.java new file mode 100644 index 0000000..4db70ed --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/exception/NBotInitializationException.java @@ -0,0 +1,27 @@ +package fr.neutronstars.nbot.exception; + +/** + * Created by NeutronStars on 30/07/2017 + */ +public class NBotInitializationException extends NBotException +{ + public NBotInitializationException() + { + super(); + } + + public NBotInitializationException(String message) + { + super(message); + } + + public NBotInitializationException(Throwable cause) + { + super(cause); + } + + public NBotInitializationException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/exception/NBotPluginException.java b/src/main/java/fr/neutronstars/nbot/exception/NBotPluginException.java new file mode 100644 index 0000000..2ee4ce7 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/exception/NBotPluginException.java @@ -0,0 +1,27 @@ +package fr.neutronstars.nbot.exception; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public class NBotPluginException extends NBotException +{ + public NBotPluginException() + { + super(); + } + + public NBotPluginException(String message) + { + super(message); + } + + public NBotPluginException(Throwable cause) + { + super(cause); + } + + public NBotPluginException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/listener/NBotListener.java b/src/main/java/fr/neutronstars/nbot/listener/NBotListener.java new file mode 100644 index 0000000..fabf599 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/listener/NBotListener.java @@ -0,0 +1,63 @@ +package fr.neutronstars.nbot.listener; + +import fr.neutronstars.nbot.NBot; +import fr.neutronstars.nbot.entity.Guild; +import fr.neutronstars.nbot.entity.Message; +import fr.neutronstars.nbot.entity.User; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.plugin.PluginManager; +import net.dv8tion.jda.core.entities.Game; +import net.dv8tion.jda.core.events.ReadyEvent; +import net.dv8tion.jda.core.events.message.MessageReceivedEvent; +import net.dv8tion.jda.core.hooks.ListenerAdapter; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public class NBotListener extends ListenerAdapter +{ + private final NBotLogger logger = NBotLogger.getLogger("NBot"); + private final PluginManager pluginManager; + + public NBotListener(PluginManager pluginManager) + { + this.pluginManager = pluginManager; + } + + public void onReady(ReadyEvent event) + { + pluginManager.enablePlugins(); + + StringBuilder builder = new StringBuilder("\n-------------------------------\n") + .append(event.getJDA().getSelfUser().getName()).append(" is Ready.\n-------------------------------"); + + for(net.dv8tion.jda.core.entities.Guild guild : event.getJDA().getGuilds()) + { + Guild guild1 = NBot.getGuild(guild); + builder.append("\n -> ").append(guild1.getName()); + } + builder.append("\n-------------------------------"); + + String playing = NBot.getConfiguration().getString("playing"); + if(playing != null && !playing.equalsIgnoreCase("null")) + NBot.getJDA().getPresence().setGame(Game.of(playing)); + + logger.log(builder.toString()); + + NBot.getConsole(); + } + + public void onMessageReceived(MessageReceivedEvent event) + { + if(event.getAuthor().isBot() || event.getTextChannel() == null) return; + Guild guild = NBot.getGuild(event.getGuild()); + String message = event.getMessage().getContent(); + if(!message.startsWith(guild.getPrefix())) return; + + message = message.replaceFirst(guild.getPrefix(), ""); + Message message1 = new Message(event.getMessage()); + + if(guild.executeCommand(new User(event.getAuthor()), message, message1)) + message1.deleteTheMessage(); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/logger/JDALogListener.java b/src/main/java/fr/neutronstars/nbot/logger/JDALogListener.java new file mode 100644 index 0000000..c80fc64 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/logger/JDALogListener.java @@ -0,0 +1,22 @@ +package fr.neutronstars.nbot.logger; + +import net.dv8tion.jda.core.utils.SimpleLog; +import net.dv8tion.jda.core.utils.SimpleLog.LogListener; + +/** + * Created by NeutronStars on 31/07/2017 + */ +public class JDALogListener implements LogListener +{ + private final NBotLogger logger = NBotLogger.getLogger("JDA"); + + public void onLog(SimpleLog log, SimpleLog.Level logLevel, Object message) + { + logger.log(Level.valueOf(logLevel.toString()), message.toString(), false); + } + + public void onError(SimpleLog log, Throwable err) + { + logger.logThrowable(err, false); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/logger/Level.java b/src/main/java/fr/neutronstars/nbot/logger/Level.java new file mode 100644 index 0000000..9e219e1 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/logger/Level.java @@ -0,0 +1,13 @@ +package fr.neutronstars.nbot.logger; + +/** + * Level for indication in the logger. + * @author NeutronStars + * @version 1.0.0 + * @since 1.0.0 + */ + +public enum Level +{ + ALL, TRACE, DEBUG, INFO, WARNING, FATAL, OFF; +} diff --git a/src/main/java/fr/neutronstars/nbot/logger/NBotLogger.java b/src/main/java/fr/neutronstars/nbot/logger/NBotLogger.java new file mode 100644 index 0000000..99b24eb --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/logger/NBotLogger.java @@ -0,0 +1,120 @@ +package fr.neutronstars.nbot.logger; + +import net.dv8tion.jda.core.utils.SimpleLog; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Created by NeutronStars on 31/07/2017 + */ +public final class NBotLogger +{ + + private static final Map loggers = new HashMap<>(); + private static final List messages = new ArrayList<>(); + private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yy-HH:mm:ss");; + private static String pattern = "[%1$s] [%2$s] %3$s : %4$s"; + + static{ + SimpleLog.addListener(new JDALogListener()); + } + + public static NBotLogger getLogger(String name) + { + if(!loggers.containsKey(name)) loggers.put(name, new NBotLogger(name)); + return loggers.get(name); + } + + public static String getPattern() + { + return pattern; + } + + public static String getDateFormat() + { + return simpleDateFormat.toPattern(); + } + + public static void setDateFormat(String dateFormat) + { + simpleDateFormat = new SimpleDateFormat(dateFormat); + } + + public static void setPattern(String pattern) + { + NBotLogger.pattern = pattern; + } + + public static void save(String folder, String name) throws IOException + { + File folderFile = new File(folder); + if(!folderFile.exists()) folderFile.mkdir(); + File file = new File(folderFile, name+".log"); + int number = 1; + while(file.exists()) + { + file = new File(folderFile, name+" ("+number+").log"); + number++; + } + + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + for(String line : messages) + { + writer.write(line); + writer.newLine(); + } + writer.flush(); + writer.close(); + messages.clear(); + } + + private final String name; + + private NBotLogger(String name) + { + this.name = name; + } + + public void log(String msg) + { + log(Level.INFO, msg); + } + + public void log(Level level, String msg) + { + log(level, msg, true); + } + + public void log(Level level, String msg, boolean show) + { + if(level == Level.DEBUG || level == Level.TRACE) return; + + String line = String.format(pattern, nowTimeFormat(), name, level, msg); + messages.add(line); + if(show) System.out.println(line); + } + + public void logThrowable(Throwable throwable) + { + logThrowable(throwable, true); + } + + public void logThrowable(Throwable throwable, boolean show) + { + StringBuilder builder = new StringBuilder(); + builder.append(throwable); + for (StackTraceElement traceElement : throwable.getStackTrace()) + builder.append("\n\tat ").append(traceElement); + log(Level.FATAL, builder.toString(), show); + } + + public String nowTimeFormat() + { + return simpleDateFormat.format(new Date()); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/plugin/NBotClassLoader.java b/src/main/java/fr/neutronstars/nbot/plugin/NBotClassLoader.java new file mode 100644 index 0000000..cb8527a --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/plugin/NBotClassLoader.java @@ -0,0 +1,24 @@ +package fr.neutronstars.nbot.plugin; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * Created by NeutronStars on 01/08/2017 + */ +final class NBotClassLoader extends URLClassLoader +{ + private final NBotPlugin plugin; + + protected NBotClassLoader(String main, ClassLoader parent,File file) throws Exception{ + super(new URL[]{file.toURI().toURL()}, parent); + Class clazz = Class.forName(main, true, this); + plugin = clazz.asSubclass(NBotPlugin.class).newInstance(); + plugin.setClassLoader(this); + } + + public NBotPlugin getPlugin() { + return plugin; + } +} diff --git a/src/main/java/fr/neutronstars/nbot/plugin/NBotPlugin.java b/src/main/java/fr/neutronstars/nbot/plugin/NBotPlugin.java new file mode 100644 index 0000000..5cdd975 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/plugin/NBotPlugin.java @@ -0,0 +1,73 @@ +package fr.neutronstars.nbot.plugin; + +import fr.neutronstars.nbot.exception.NBotPluginException; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public abstract class NBotPlugin +{ + private NBotClassLoader classLoader; + private final String[] authors; + private String name, version; + + protected NBotPlugin(String... authors) + { + this.authors = authors; + } + + public String getName() + { + return name; + } + + public String getVersion() + { + return version; + } + + public final String[] getAuthors() + { + return authors; + } + + public String getAuthorsToString() + { + StringBuilder builder = new StringBuilder(); + for(int i = 0; ; i++) + { + if(i == authors.length) return builder.length() > 0 ? builder.toString() : "Not author"; + if(i != 0) builder.append(", "); + builder.append(authors[i]); + } + } + + public NBotClassLoader getClassLoader() + { + return classLoader; + } + + protected final void setClassLoader(NBotClassLoader classLoader) + { + String error = this.classLoader != null ? "The ClassLoader is already initialized." : classLoader == null ? "The ClassLoader cannot be null." : null; + if(error != null) throw new NBotPluginException(error); + this.classLoader = classLoader; + } + + public final void setName(String name) + { + if(this.name != null) throw new NBotPluginException("The plugin name is already initialized."); + this.name = name; + } + + public final void setVersion(String version) + { + this.version = version; + } + + public void onLoad(){} + + public void onEnable(){} + + public void onDisable(){} +} diff --git a/src/main/java/fr/neutronstars/nbot/plugin/PluginManager.java b/src/main/java/fr/neutronstars/nbot/plugin/PluginManager.java new file mode 100644 index 0000000..562e4f1 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/plugin/PluginManager.java @@ -0,0 +1,99 @@ +package fr.neutronstars.nbot.plugin; + +import fr.neutronstars.nbot.exception.NBotPluginException; +import fr.neutronstars.nbot.logger.NBotLogger; +import fr.neutronstars.nbot.util.JSONReader; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarFile; + +/** + * Created by NeutronStars on 01/08/2017 + */ +public final class PluginManager +{ + private final Map, NBotPlugin> plugins = new HashMap<>(); + private final NBotLogger logger = NBotLogger.getLogger("NBot"); + private final String loadedFormat, enabledFormat, disabledFormat; + + public PluginManager(String loadedFormat, String enabledFormat, String disabledFormat) + { + this.loadedFormat = loadedFormat; + this.enabledFormat = enabledFormat; + this.disabledFormat = disabledFormat; + for(File file : new File("plugins").listFiles()) loadPlugin(file); + } + + public T getPlugin(Class clazz) + { + return (T) plugins.get(clazz); + } + + public Collection getPlugins() + { + return new ArrayList<>(plugins.values()); + } + + private void loadPlugin(File file) + { + if(file == null || file.isDirectory() || !file.getName().endsWith(".jar")) return; + NBotPlugin nBotPlugin = loadNBotPlugin(file); + if(nBotPlugin == null) return; + nBotPlugin.onLoad(); + logger.log(String.format(loadedFormat, nBotPlugin.getName(), nBotPlugin.getVersion(), nBotPlugin.getAuthorsToString())); + } + + private NBotPlugin loadNBotPlugin(File file) + { + try(JarFile jar = new JarFile(file)) + { + JSONReader reader = new JSONReader(new BufferedReader(new InputStreamReader(jar.getInputStream(jar.getJarEntry("plugin.json"))))); + JSONObject object = reader.toJSONObject(); + + if(!object.has("main") || !object.has("name") || !object.has("version")) throw new NBotPluginException("Invalid \"plugin.json\"."); + NBotPlugin nBotPlugin = new NBotClassLoader(object.getString("main"), getClass().getClassLoader(), file).getPlugin(); + + nBotPlugin.setName(object.getString("name")); + nBotPlugin.setVersion(object.getString("version")); + + plugins.put(nBotPlugin.getClass(), nBotPlugin); + return nBotPlugin; + } + catch(Exception e) + { + logger.logThrowable(new NBotPluginException(e)); + } + return null; + } + + public void enablePlugins() + { + for(NBotPlugin nBotPlugin : plugins.values()) + { + nBotPlugin.onEnable(); + logger.log(String.format(enabledFormat, nBotPlugin.getName(), nBotPlugin.getVersion(), nBotPlugin.getAuthorsToString())); + } + } + + public void disablePlugins() + { + for(NBotPlugin nBotPlugin : plugins.values()) + { + nBotPlugin.onDisable(); + logger.log(String.format(disabledFormat, nBotPlugin.getName(), nBotPlugin.getVersion(), nBotPlugin.getAuthorsToString())); + try { + nBotPlugin.getClassLoader().close(); + } catch(IOException e) { + logger.logThrowable(e); + } + } + } +} diff --git a/src/main/java/fr/neutronstars/nbot/util/Configuration.java b/src/main/java/fr/neutronstars/nbot/util/Configuration.java new file mode 100644 index 0000000..17aa60d --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/util/Configuration.java @@ -0,0 +1,119 @@ +package fr.neutronstars.nbot.util; + +import fr.neutronstars.nbot.exception.NBotConfigurationException; +import fr.neutronstars.nbot.logger.NBotLogger; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by NeutronStars on 31/07/2017 + */ +public class Configuration +{ + private final File file; + + private JSONObject object; + + private Configuration(File file, JSONObject object) + { + this.object = object; + this.file = file; + } + + public Object get(String key) + { + return object.has(key) ? object.get(key) : null; + } + + public String getString(String key) + { + return object.has(key) ? object.getString(key) : null; + } + + public int getInt(String key) + { + return object.has(key) ? object.getInt(key) : 0; + } + + public long getLong(String key) + { + return object.has(key) ? object.getLong(key) : 0; + } + + public double getDouble(String key) + { + return object.has(key) ? object.getDouble(key) : 0; + } + + public boolean getBoolean(String key) + { + return object.has(key) ? object.getBoolean(key) : false; + } + + public List getList(String key) + { + List list = new ArrayList<>(); + + if(object.has(key)) + { + JSONArray array = object.getJSONArray(key); + for(int i = 0; i < array.length(); i++) + list.add((T) array.get(i)); + } + + return list; + } + + public > E getEnum(Class clazz, String key) + { + return object.has(key) ? object.getEnum(clazz, key) : null; + } + + public boolean has(String key) + { + return object.has(key); + } + + public void set(String key, Object value) + { + object.put(key, value); + } + + public void clear() + { + object = new JSONObject(); + } + + public void save() + { + try(JSONWriter writer = new JSONWriter(file)) + { + writer.write(object); + writer.flush(); + } + catch(IOException ioe) + { + NBotLogger.getLogger("NBot").logThrowable(new NBotConfigurationException(ioe)); + } + } + + public static Configuration loadConfiguration(File file) + { + if(!file.exists()) return new Configuration(file, new JSONObject()); + + try + { + return new Configuration(file, new JSONReader(file).toJSONObject()); + } + catch(IOException ioe) + { + NBotLogger.getLogger("NBot").logThrowable(new NBotConfigurationException(ioe)); + } + return null; + } +} diff --git a/src/main/java/fr/neutronstars/nbot/util/JSONReader.java b/src/main/java/fr/neutronstars/nbot/util/JSONReader.java new file mode 100644 index 0000000..23ed1e8 --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/util/JSONReader.java @@ -0,0 +1,157 @@ +package fr.neutronstars.nbot.util; + +import fr.neutronstars.nbot.logger.NBotLogger; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by NeutronStars on 14/07/2017 + * + */ +public final class JSONReader +{ + private final String json; + + public JSONReader(String path) throws IOException + { + this(new File(path)); + } + + public JSONReader(File file) throws IOException + { + this(new InputStreamReader(new FileInputStream(file))); + } + + public JSONReader(Reader reader) throws IOException + { + this(new BufferedReader(reader)); + } + + public JSONReader(BufferedReader reader) throws IOException + { + json = load(reader); + } + + private String load(BufferedReader reader) throws IOException + { + StringBuilder builder = new StringBuilder(); + + while(reader.ready()) builder.append(reader.readLine()); + + reader.close(); + + return builder.length() == 0 ? "[]" : builder.toString(); + } + + public static List toList(String path) + { + return toList(new File(path)); + } + + public static List toList(File file) + { + try + { + return toList(new InputStreamReader(new FileInputStream(file))); + } + catch(IOException e) + { + NBotLogger.getLogger("NBot").logThrowable(e); + } + return new ArrayList<>(); + } + + public static List toList(Reader reader) + { + return toList(new BufferedReader(reader)); + } + + public static List toList(BufferedReader bufferedReader) + { + List list= new ArrayList<>(); + + try + { + JSONReader reader = new JSONReader(bufferedReader); + JSONArray array = reader.toJSONArray(); + for(int i = 0; i < array.length(); i++) + { + try + { + list.add((E) array.get(i)); + }catch(ClassCastException e){} + } + } + catch(IOException e) + { + NBotLogger.getLogger("NBot").logThrowable(e); + } + + return list; + } + + public static Map toMap(String path) + { + return toMap(new File(path)); + } + + public static Map toMap(File file) + { + try + { + return toMap(new InputStreamReader(new FileInputStream(file))); + } + catch(IOException e) + { + NBotLogger.getLogger("NBot").logThrowable(e); + } + return new HashMap<>(); + } + + public static Map toMap(Reader reader) + { + return toMap(new BufferedReader(reader)); + } + + public static Map toMap(BufferedReader bufferedReader) + { + Map map = new HashMap<>(); + + try + { + JSONReader reader = new JSONReader(bufferedReader); + JSONObject object = reader.toJSONObject(); + for(String key : object.keySet()) + { + Object obj = object.get(key); + try + { + map.put(key, (V) object.get(key)); + } + catch(ClassCastException e) {} + } + } + catch(IOException e) + { + NBotLogger.getLogger("NBot").logThrowable(e); + } + + return map; + } + + public JSONArray toJSONArray() + { + return new JSONArray(json); + } + + public JSONObject toJSONObject() + { + return new JSONObject(json); + } +} diff --git a/src/main/java/fr/neutronstars/nbot/util/JSONWriter.java b/src/main/java/fr/neutronstars/nbot/util/JSONWriter.java new file mode 100644 index 0000000..cfa7dfb --- /dev/null +++ b/src/main/java/fr/neutronstars/nbot/util/JSONWriter.java @@ -0,0 +1,117 @@ +package fr.neutronstars.nbot.util; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.*; + +/** + * Created by NeutronStars on 14/07/2017 + */ +public final class JSONWriter implements Closeable +{ + private final BufferedWriter writer; + private int space; + + public JSONWriter(String path) throws IOException + { + this(new File(path)); + } + + public JSONWriter(File file) throws IOException + { + this(new FileWriter(file)); + } + + public JSONWriter(Writer writer) + { + this(new BufferedWriter(writer)); + } + + public JSONWriter(BufferedWriter writer) + { + this.writer = writer; + } + + public void write(JSONArray array) throws IOException + { + writer.write("["); + writer.newLine(); + + this.space+=2; + String space = spaceBuilder(); + + for(int i = 0; i < array.length(); i++) + { + Object object = array.get(i); + + if(object instanceof Number || object instanceof Boolean) writer.write(space+object); + else if(object instanceof JSONObject) write((JSONObject) object, true); + else if(object instanceof JSONArray) write((JSONArray) object); + else writer.write(space+"\""+object.toString()+"\""); + + if(i < array.length()-1) writer.write(","); + writer.newLine(); + } + + this.space-=2; + space = spaceBuilder(); + + writer.write(space+"]"); + } + + private void write(JSONObject jsonObject, boolean spacing) throws IOException + { + writer.write((spacing ? spaceBuilder() : "") + "{"); + writer.newLine(); + + this.space+=2; + String space = spaceBuilder(); + + int i = 0; + final int max = jsonObject.length(); + + for(String key : jsonObject.keySet()) + { + writer.write(space+"\""+key+"\":"); + Object object = jsonObject.get(key); + + if(object instanceof Number || object instanceof Boolean) writer.write(object.toString()); + else if(object instanceof JSONObject) write((JSONObject) object, false); + else if(object instanceof JSONArray) write((JSONArray) object); + else writer.write("\""+object.toString()+"\""); + + if(i < max-1) writer.write(","); + i++; + + writer.newLine(); + } + + this.space-=2; + space = spaceBuilder(); + + writer.write(space+"}"); + } + + public void write(JSONObject jsonObject) throws IOException + { + write(jsonObject, false); + } + + private String spaceBuilder() + { + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < space; i++) builder.append(" "); + return builder.length() == 0 ? "" : builder.toString(); + } + + public void flush() throws IOException + { + writer.flush(); + } + + public void close() throws IOException + { + writer.close(); + } +}