diff --git a/.gitignore b/.gitignore index 52093ae..2a00cc8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,8 @@ hs_err_pid* # custom -.idea/ +.idea/* +!.idea/icon.svg src/test/ *.iml target/ diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 0000000..1a54548 --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/pom.xml b/pom.xml index 554c6e1..0854428 100644 --- a/pom.xml +++ b/pom.xml @@ -4,16 +4,66 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.example - RoboFlask - 1.0 + RoboFlask + com.devflask + roboflask + 3.4.2 + jar + https://dehys.com/${project.name} + + RoboFlask is a discord bot made by the devflask community. It's a bot designed to do everything with the help of the existing features and future implementations from anyone. Want to contribute? Read CONTRIBUTE.md + - 1.4.31 - true 17 + com.devflask.roboflask.Robo + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + ${java.version} + ${java.version} + + + + maven-shade-plugin + 3.2.1 + + + + ${mainClass} + + + false + + + + package + + shade + + + + + + + com.jcraft @@ -42,19 +92,14 @@ org.apache.logging.log4j log4j-core - 2.14.0 + 2.17.0 - com.moandjiezana.toml - toml4j - 0.7.2 + com.google.code.gson + gson + 2.8.9 - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - @@ -68,96 +113,6 @@ maven-central https://repo1.maven.org/maven2/ - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/main/java - - - - - test-compile - test-compile - - - ${project.basedir}/src/test/kotlin - ${project.basedir}/src/test/java - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - 17 - 17 - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - maven-shade-plugin - 3.2.1 - - - - com.devflask.roboflask.Robo - - - false - - - - package - - shade - - - - - - - \ No newline at end of file diff --git a/src/main/java/com/devflask/roboflask/Bot.java b/src/main/java/com/devflask/roboflask/Bot.java index e9508b9..53270ab 100644 --- a/src/main/java/com/devflask/roboflask/Bot.java +++ b/src/main/java/com/devflask/roboflask/Bot.java @@ -1,15 +1,15 @@ package com.devflask.roboflask; +import com.devflask.roboflask.command.CommandManager; import com.devflask.roboflask.command.moderation.Ban; import com.devflask.roboflask.command.moderation.Get; +import com.devflask.roboflask.command.moderation.Kick; import com.devflask.roboflask.command.moderation.Unban; import com.devflask.roboflask.command.util.Help; import com.devflask.roboflask.command.util.Info; -import com.devflask.roboflask.command.Command; -import com.devflask.roboflask.command.CommandManager; import com.devflask.roboflask.command.util.Ping; -import com.devflask.roboflask.command.moderation.Kick; -import com.devflask.roboflask.configuration.ConfigManager; +import com.devflask.roboflask.database.Database; +import com.devflask.roboflask.interfaces.Command; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Activity; @@ -17,29 +17,46 @@ import javax.security.auth.login.LoginException; import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; public class Bot { - public static Map botMap = new HashMap<>(); public int id; - private static final CommandManager commandManager = new CommandManager();; - private ConfigManager configManager; + private static final CommandManager commandManager = new CommandManager(); + private final String token; + private Database database; + private JDA jda; - public Bot(String token) throws LoginException, InterruptedException { - this.id = generateId(); - botMap.put(this, this.id); + public Bot(String token) { + this.token = token; + setup(); + } + public Bot(String token, Database database) { this.token = token; - initJDA(); - initializeCommands(); + this.database = database.connect(); + setup(); + } + + private void setup() { + this.id = Robo.generateId(); + Robo.bots.add(this); + + try { + initJDA(); + initCommands(); + } catch (LoginException | InterruptedException e) { + e.printStackTrace(); + } + } + + private void initJDA() throws LoginException, InterruptedException { + jda = setupJDA().build(); + jda.awaitReady(); } - public void initializeCommands(){ + public void initCommands() { registerCommands( new Help(), new Ping(), @@ -50,24 +67,15 @@ public void initializeCommands(){ new Get() ); } - - private void initJDA() throws LoginException, InterruptedException { - JDA bot = setupJDA().build(); - bot.awaitReady(); - } - private JDABuilder setupJDA(){ - JDABuilder builder = JDABuilder.create(this.token == null ? System.getenv("RoboflaskToken") : this.token, getIntents()); + private JDABuilder setupJDA() { + JDABuilder builder = JDABuilder.create(this.token == null ? System.getenv("RoboFlaskToken") : this.token, getIntents()); builder.setActivity(Activity.watching("running on cd")); builder.addEventListeners(commandManager); return builder; } - private void setupDatabase(){ - - } - - private EnumSet getIntents(){ + private EnumSet getIntents() { return EnumSet.of( GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MESSAGES, @@ -79,27 +87,29 @@ private EnumSet getIntents(){ ); } - private void registerCommands(Command ... commands){ + private void registerCommands(Command... commands) { for (Command cmd : commands) commandManager.addCommand(cmd); } - public static CommandManager getCommandManager(){ + public static CommandManager getCommandManager() { return commandManager; } - private int generateId(){ - //generate - int i = new Random().nextInt(10000000, 99999999); - - //check availability - for (Bot bot : botMap.keySet()){ - while (bot.id == i){ - i = new Random().nextInt(10000000, 99999999); - } - } + //getters + public Database getDatabase() { + return this.database; + } - return i; + public JDA getJDA() { + return this.jda; } + public int getId() { + return this.id; + } + //setters + public void setDatabase(Database database) { + this.database = database; + } } diff --git a/src/main/java/com/devflask/roboflask/Robo.java b/src/main/java/com/devflask/roboflask/Robo.java index e1d2ab6..7d318a9 100644 --- a/src/main/java/com/devflask/roboflask/Robo.java +++ b/src/main/java/com/devflask/roboflask/Robo.java @@ -6,106 +6,121 @@ import javax.security.auth.login.LoginException; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; -public class Robo { - - public static Map roboMap = new HashMap<>(); - public int id; +public class Robo { private static final Logger LOGGER = LogManager.getLogger(Robo.class); - public Bot bot = null; - public Database database = null; - private static String[] arguments; + public static final List databases = new ArrayList<>(); + public static final List bots = new ArrayList<>(); + public static List ids = new ArrayList<>(); + public static Robo instance; //Way into the program - public static void main(String[] args) throws SQLException, ClassNotFoundException { - + public static void main(String[] args) { try { - arguments = args; - Robo robo = new Robo().create(); + instance = new Robo().setup(args); } catch (LoginException | InterruptedException e) { e.printStackTrace(); } } - public Robo(){ - this.id = generateId(); - roboMap.put(this, this.id); - LOGGER.info("Created Robo with id: "+this.id); - } - - //Setters - public void setBot(Bot bot) { - this.bot = bot; + public Robo setup(String[] arguments) throws LoginException, InterruptedException { + //Check initial bot + if (arguments.length < 1) { + LOGGER.error("RoboFlask has no initial bot!"); + LOGGER.info("Exiting..."); + System.exit(1); + } else if (arguments.length == 1) { + addBot(new Bot(arguments[0])); + } else if (arguments.length > 2) { + if (arguments.length > 4) { + String host, username, password; + host = arguments[1]; + username = arguments[2]; + password = arguments[3]; + addBot(new Bot(arguments[0], new Database(host, username, password))); + } else { + LOGGER.warn("RoboFlask has no database! Check the credentials and try again"); + LOGGER.info("Defaulting to no database..."); + addBot(new Bot(arguments[0])); + } + } + return this; } - public void setDatabase(Database database) { - this.database = database; - } + public static int generateId() { + //generate + int i = new Random().nextInt(Integer.MAX_VALUE); - public static void setArguments(String[] arguments) { - Robo.arguments = arguments; - } + //check availability + for (int id : ids) { + while (id == i) { + i = new Random().nextInt(Integer.MAX_VALUE); + } + } - //Getters - public Bot getBot() { - return bot; + ids.add(i); + return i; } - public Database getDatabase() { - return database; + public static void addBot(Bot bot) { + bots.add(bot); } - public int getId() { - return id; + public static void removeBot(Bot bot) { + bot.getJDA().shutdown(); + bots.remove(bot); } - public Robo create() throws LoginException, InterruptedException, SQLException, ClassNotFoundException { - - //Check bot - if (bot == null){ - if (arguments.length < 1){ - LOGGER.error("Robo:"+this.id+" has no bot bound to it!"); - System.exit(1); - }else { - bot = new Bot(arguments[0]); + public static void removeBot(int id) { + for (Bot bot : bots) { + if (bot.getId() == id) { + removeBot(bot); + break; } } + } - //Check database - if (database == null){ - if (arguments.length < 3){ - LOGGER.info("Database remains unset for Robo:"+this.id); - return this; - }else { - String pass = ""; - if (arguments.length > 3){ - pass = arguments[3]; - } - database = new Database(arguments[1], arguments[2], pass).connect(); + public static Bot getBot(int id) { + for (Bot bot : bots) { + if (bot.getId() == id) { + return bot; } } + return null; + } - return this; + public static void addDatabase(Database database) { + databases.add(database); } - private int generateId(){ - //generate - int i = new Random().nextInt(10000000, 99999999); + public static void removeDatabase(Database database) throws SQLException { + database.disconnect(); + databases.remove(database); + } - //check availability - for (Robo robo : roboMap.keySet()){ - while (robo.id == i){ - i = new Random().nextInt(10000000, 99999999); + public static void removeDatabase(int id) throws SQLException { + for (Database database : databases) { + if (database.getId() == id) { + removeDatabase(database); + break; } } - - return i; } + public static Database getDatabase(int id) { + for (Database database : databases) { + if (database.getId() == id) { + return database; + } + } + return null; + } } diff --git a/src/main/java/com/devflask/roboflask/command/CommandManager.java b/src/main/java/com/devflask/roboflask/command/CommandManager.java index fc2f8c6..b48ba8a 100644 --- a/src/main/java/com/devflask/roboflask/command/CommandManager.java +++ b/src/main/java/com/devflask/roboflask/command/CommandManager.java @@ -1,6 +1,7 @@ package com.devflask.roboflask.command; import com.devflask.roboflask.configuration.Config; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import com.devflask.roboflask.util.Messages; import net.dv8tion.jda.api.entities.Message; diff --git a/src/main/java/com/devflask/roboflask/command/moderation/Ban.java b/src/main/java/com/devflask/roboflask/command/moderation/Ban.java index df0a350..ded1b4f 100644 --- a/src/main/java/com/devflask/roboflask/command/moderation/Ban.java +++ b/src/main/java/com/devflask/roboflask/command/moderation/Ban.java @@ -1,7 +1,7 @@ package com.devflask.roboflask.command.moderation; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import com.devflask.roboflask.util.Messages; import net.dv8tion.jda.api.Permission; @@ -10,7 +10,9 @@ import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; public class Ban implements Command { diff --git a/src/main/java/com/devflask/roboflask/command/moderation/Get.java b/src/main/java/com/devflask/roboflask/command/moderation/Get.java index dd7dd3b..4431624 100644 --- a/src/main/java/com/devflask/roboflask/command/moderation/Get.java +++ b/src/main/java/com/devflask/roboflask/command/moderation/Get.java @@ -1,11 +1,12 @@ package com.devflask.roboflask.command.moderation; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.interfaces.Command; import net.dv8tion.jda.api.Permission; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; public class Get implements Command { diff --git a/src/main/java/com/devflask/roboflask/command/moderation/Kick.java b/src/main/java/com/devflask/roboflask/command/moderation/Kick.java index d297183..969a903 100644 --- a/src/main/java/com/devflask/roboflask/command/moderation/Kick.java +++ b/src/main/java/com/devflask/roboflask/command/moderation/Kick.java @@ -1,7 +1,7 @@ package com.devflask.roboflask.command.moderation; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import com.devflask.roboflask.util.Messages; import net.dv8tion.jda.api.Permission; @@ -27,7 +27,7 @@ public class Kick implements Command { } @Override - public @NotNull String getHelp() { + public @NotNull String getDescription() { return "Kicks the member specified - !kick <@Person> [reason]"; } diff --git a/src/main/java/com/devflask/roboflask/command/moderation/Unban.java b/src/main/java/com/devflask/roboflask/command/moderation/Unban.java index 973a479..49efd11 100644 --- a/src/main/java/com/devflask/roboflask/command/moderation/Unban.java +++ b/src/main/java/com/devflask/roboflask/command/moderation/Unban.java @@ -1,7 +1,7 @@ package com.devflask.roboflask.command.moderation; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import com.devflask.roboflask.util.Messages; import net.dv8tion.jda.api.Permission; @@ -33,7 +33,7 @@ public Collection getRequiredPermissions(){ return set; } - public @NotNull String getHelp() { + public @NotNull String getDescription() { return "Unbans a specified user."; } diff --git a/src/main/java/com/devflask/roboflask/command/util/Help.java b/src/main/java/com/devflask/roboflask/command/util/Help.java index c246c56..613e432 100644 --- a/src/main/java/com/devflask/roboflask/command/util/Help.java +++ b/src/main/java/com/devflask/roboflask/command/util/Help.java @@ -1,9 +1,7 @@ package com.devflask.roboflask.command.util; -import com.devflask.roboflask.Bot; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; -import com.devflask.roboflask.command.CommandManager; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; @@ -31,7 +29,7 @@ public class Help implements Command { } @Override - public @NotNull String getHelp() { + public @NotNull String getDescription() { return "Retrieves help from the bot."; } @@ -41,13 +39,13 @@ public void execute(PrivateMessageReceivedEvent event) { public void execute(GuildMessageReceivedEvent event) { StringBuilder commands = new StringBuilder(); - HashMap commandsMap = new HashMap(); + HashMap commandsMap = new HashMap<>(); for (Command c : getManager().getCommands()){ - System.out.println(c.getName()+" - "+c.getHelp()); + System.out.println(c.getName() + " - " + c.getDescription()); commands .append(c.getName()) .append(" - ") - .append(c.getHelp()) + .append(c.getDescription()) .append("\n") ; } @@ -55,7 +53,7 @@ public void execute(GuildMessageReceivedEvent event) { commandsMap.put("Commands", commands.toString()); event.getChannel().sendMessage(MessageUtil.getInformative( - event.getMember().getEffectiveName(), + Objects.requireNonNull(event.getMember()).getEffectiveName(), event.getAuthor().getAvatarUrl(), "", "", diff --git a/src/main/java/com/devflask/roboflask/command/util/Info.java b/src/main/java/com/devflask/roboflask/command/util/Info.java index 7b3aa04..52156df 100644 --- a/src/main/java/com/devflask/roboflask/command/util/Info.java +++ b/src/main/java/com/devflask/roboflask/command/util/Info.java @@ -1,10 +1,10 @@ package com.devflask.roboflask.command.util; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.interfaces.Command; import com.devflask.roboflask.util.MessageUtil; import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import org.apache.logging.log4j.LogManager; @@ -15,10 +15,8 @@ import javax.management.AttributeList; import javax.management.MBeanServer; import javax.management.ObjectName; -import java.awt.*; import java.lang.management.ManagementFactory; import java.util.*; -import java.util.List; public class Info implements Command { @@ -38,7 +36,7 @@ public class Info implements Command { } @Override - public @NotNull String getHelp() { + public @NotNull String getDescription() { return "Retrieves information about the bot."; } @@ -93,9 +91,13 @@ private MessageEmbed messageEmbed(JDA jda){ "", "Information", fields, - "\n__RoboFlask__ bot software, a very powerful discord bot. Lots of features from fun games to useful utilities like __doc parsing__ and __code management__. RoboFlask is mainly focused towards the __programming community__ of discord which is why it provides a lot of __tools__ for code management\nā€ƒ" + - "\n**Getting Started**\n" + - "Start by using the `help` command and see what the bot has to offer. This can vary from guild to guild as they can easily disable features. If you want to see all features the bot provides, check https://github.com/devflask/RoboFlask.\n**ā€ƒ**" + """ + + __RoboFlask__ bot software, a very powerful discord bot. Lots of features from fun games to useful utilities like __doc parsing__ and __code management__. RoboFlask is mainly focused towards the __programming community__ of discord which is why it provides a lot of __tools__ for code management + ā€ƒ + **Getting Started** + Start by using the `help` command and see what the bot has to offer. This can vary from guild to guild as they can easily disable features. If you want to see all features the bot provides, check https://github.com/devflask/RoboFlask. + **ā€ƒ**""" ).build(); } diff --git a/src/main/java/com/devflask/roboflask/command/util/Ping.java b/src/main/java/com/devflask/roboflask/command/util/Ping.java index 42042b5..ced3e62 100644 --- a/src/main/java/com/devflask/roboflask/command/util/Ping.java +++ b/src/main/java/com/devflask/roboflask/command/util/Ping.java @@ -1,9 +1,7 @@ package com.devflask.roboflask.command.util; -import com.devflask.roboflask.Bot; -import com.devflask.roboflask.command.Command; import com.devflask.roboflask.command.CommandInformation; -import com.devflask.roboflask.command.CommandManager; +import com.devflask.roboflask.interfaces.Command; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import org.apache.logging.log4j.LogManager; @@ -30,21 +28,17 @@ public class Ping implements Command { } @Override - public @NotNull String getHelp() { + public @NotNull String getDescription() { return "Pings the server."; } public void execute(GuildMessageReceivedEvent event) { - event.getJDA().getRestPing().queue(ping -> { - event.getChannel().sendMessage("**My ping is: **"+ping).queue(); - }); + event.getJDA().getRestPing().queue(ping -> event.getChannel().sendMessage("**My ping is: **" + ping).queue()); LOGGER.debug("PONG in guild channel with id: " + event.getChannel().getId()); } public void execute(PrivateMessageReceivedEvent event) { - event.getJDA().getRestPing().queue(ping -> { - event.getChannel().sendMessage("**My ping is: **"+ping).queue(); - }); + event.getJDA().getRestPing().queue(ping -> event.getChannel().sendMessage("**My ping is: **" + ping).queue()); LOGGER.debug("PONG in private channel with id: " + event.getChannel().getId()); } diff --git a/src/main/java/com/devflask/roboflask/configuration/ConfigManager.java b/src/main/java/com/devflask/roboflask/configuration/ConfigManager.java deleted file mode 100644 index 021b5f4..0000000 --- a/src/main/java/com/devflask/roboflask/configuration/ConfigManager.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.devflask.roboflask.configuration; - -import com.moandjiezana.toml.Toml; - -public class ConfigManager { - - public ConfigManager(Toml ConfigurationFile) { - - } - -} diff --git a/src/main/java/com/devflask/roboflask/database/Database.java b/src/main/java/com/devflask/roboflask/database/Database.java index cb56ccc..53ab34c 100644 --- a/src/main/java/com/devflask/roboflask/database/Database.java +++ b/src/main/java/com/devflask/roboflask/database/Database.java @@ -1,70 +1,125 @@ package com.devflask.roboflask.database; +import com.devflask.roboflask.Robo; + import java.sql.*; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; +import java.util.ArrayList; +import java.util.List; public class Database { - public static Map databaseMap = new HashMap<>(); public int id; - boolean connected; - - String host; - String username; + private final String host; + private final String username; private final String password; - Connection connection; + public Connection connection; public Database(String host, String username, String password) { - this.id = generateId(); - databaseMap.put(this, this.id); + this.id = Robo.generateId(); + Robo.addDatabase(this); - connected = false; this.host = host; this.username = username; this.password = password; } - public Database connect() throws SQLException, ClassNotFoundException { - Class.forName("com.mysql.cj.jdbc.Driver"); - connection = DriverManager.getConnection( - host, - username, - password - ); + public Database connect() { + try { + connection = DriverManager.getConnection( + host, + username, + password + ); + + this.executeUpdate("CREATE TABLE IF NOT EXISTS `profiles` (" + + " userID VARCHAR(255) not NULL, " + + " guildID VARCHAR(255) not NULL, " + + " level INTEGER, " + + " xp INTEGER, " + + " xpToNextLevel INTEGER, " + + " coins INTEGER, " + + " messages INTEGER, " + + " profileBanner TEXT, " + + " profileBorder TEXT, " + + " profileColor INTEGER, " + + " PRIMARY KEY (userID, guildID)" + + ");"); + + this.executeUpdate("CREATE TABLE IF NOT EXISTS `guilds` (\n" + + " `guildID` VARCHAR(255) NOT NULL,\n" + + " `prefix` VARCHAR(255),\n" + + " `customCommands` JSON,\n" + + " `customRanks` JSON,\n" + + " `totalCommands` INTEGER,\n" + + " `totalMessages` INTEGER,\n" + + " PRIMARY KEY (`guildID`)\n" + + ");"); + + this.executeUpdate("CREATE TABLE IF NOT EXISTS `commands` (\n" + + " `commandID` INTEGER NOT NULL AUTO_INCREMENT,\n" + + " `guildID` VARCHAR(255) NOT NULL,\n" + + " `data` JSON,\n" + + " PRIMARY KEY (`commandID`, `guildID`)\n" + + ");"); + + this.executeUpdate("CREATE TABLE IF NOT EXISTS `ranks` (\n" + + " `rankID` INTEGER NOT NULL AUTO_INCREMENT,\n" + + " `guildID` VARCHAR(255) NOT NULL,\n" + + " `data` JSON,\n" + + " PRIMARY KEY (`rankID`, `guildID`)\n" + + ");"); + + + return this; + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + + public Database disconnect() throws SQLException { + connection.close(); return this; } public ResultSet executeQuery(String query) throws SQLException { + if (connection.isClosed()) return null; Statement stmt = connection.createStatement(); return stmt.executeQuery(query); } - public int executeUpdate(String query) throws SQLException { + public void executeUpdate(String query) throws SQLException { + if (connection.isClosed()) return; Statement stmt = connection.createStatement(); - return stmt.executeUpdate(query); - } - - public Database disconnect() throws SQLException { - connection.close(); - return this; + stmt.executeUpdate(query); } - private int generateId(){ - //generate - int i = new Random().nextInt(10000000, 99999999); + //Static Methods - //check availability - for (Database database : databaseMap.keySet()){ - while (database.id == i){ - i = new Random().nextInt(10000000, 99999999); + public static Database getDatabase(int id) { + for (Database database : Robo.databases) { + if (database.id == id) { + return database; } } + return null; + } - return i; + public static Database[] getDatabases(String host, String username, String password) { + List databaseList = new ArrayList<>(); + for (Database database : Robo.databases) { + if (database.host.equalsIgnoreCase(host) + && database.username.equalsIgnoreCase(username) + && database.password.equalsIgnoreCase(password)) { + databaseList.add(database); + } + } + return databaseList.size() == 0 ? null : databaseList.toArray(new Database[0]); } + public int getId() { + return id; + } } diff --git a/src/main/java/com/devflask/roboflask/database/DatabaseManager.java b/src/main/java/com/devflask/roboflask/database/DatabaseManager.java index e1a8558..1ce0bbc 100644 --- a/src/main/java/com/devflask/roboflask/database/DatabaseManager.java +++ b/src/main/java/com/devflask/roboflask/database/DatabaseManager.java @@ -1,9 +1,284 @@ package com.devflask.roboflask.database; -public class DatabaseManager { +import com.devflask.roboflask.Bot; +import com.devflask.roboflask.Robo; +import com.devflask.roboflask.database.entry.*; +import com.google.gson.Gson; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; - public DatabaseManager(){ +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +public record DatabaseManager(Database database) { + + public static Map cache = new HashMap<>(); + + //region Profile + + public int addProfile(ProfileEntry profileEntry) { + String sql = + "INSERT INTO Profiles (userID, guildID, level, xp, xpToNextLevel, coins, messages, profileBanner, profileBorder, profileColor)" + + "VALUES ('" + + profileEntry.getMember().getId() + "', '" + + profileEntry.getMember().getGuild().getId() + "', " + + profileEntry.getLevel() + ", " + + profileEntry.getXp() + ", " + + profileEntry.getXpToNextLevel() + ", " + + profileEntry.getCoins() + ", " + + profileEntry.getMessages() + ", '" + + profileEntry.getProfileBanner() + "', '" + + profileEntry.getProfileBorder() + "', '" + + profileEntry.getProfileColor() + + "')"; + + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + return 1; + } + return 0; + } + + public int removeProfile(ProfileEntry profileEntry) { + String sql = "DELETE FROM `profiles` WHERE `userID`='" + profileEntry.getMember().getId() + "' AND `guildID`='" + profileEntry.getMember().getGuild().getId() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + return 1; + } + return 0; + } + + public int updateProfile(ProfileEntry profileEntry) { + String sql = "UPDATE `profiles` SET `level`='" + profileEntry.getLevel() + "', `xp`='" + profileEntry.getXp() + "', `xpToNextLevel`='" + profileEntry.getXpToNextLevel() + "', `coins`='" + profileEntry.getCoins() + "', `messages`='" + profileEntry.getMessages() + "', `profileBanner`='" + profileEntry.getProfileBanner() + "', `profileBorder`='" + profileEntry.getProfileBorder() + "', `profileColor`='" + profileEntry.getProfileColor() + "' WHERE `userID`='" + profileEntry.getMember().getId() + "' AND `guildID`='" + profileEntry.getMember().getGuild().getId() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + return 1; + } + return 0; + } + + public ProfileEntry fetchProfile(Member member) { + String sql = "SELECT * FROM `profiles` WHERE `userID`='" + member.getId() + "' AND `guildID`='" + member.getGuild().getId() + "';"; + try { + ResultSet rs = database.executeQuery(sql); + if (rs.next()) { + ProfileEntry dbp = new ProfileEntry( + member, + rs.getInt("level"), + rs.getInt("xp"), + rs.getInt("xpToNextLevel"), + rs.getInt("coins"), + rs.getInt("messages"), + rs.getString("profileBanner"), + rs.getString("profileBorder"), + rs.getInt("profileColor") + ); + + rs.close(); + return dbp; + } else { + rs.close(); + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + + //endregion Profile + //region Guild + + public void addGuild(GuildEntry guildEntry) { + String sql = + "INSERT INTO `guilds` (`roboID`, `guildID`)" + + "VALUES ('" + + guildEntry.getGuildID() + "', '" + + guildEntry.asJson() + "'" + + ")"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public int removeGuild(GuildEntry guildEntry) { + String sql = "DELETE FROM `guilds` WHERE `guildID`='" + guildEntry.getGuildID() + "' AND `roboID`='" + guildEntry.getRoboID() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + return 1; + } + return 0; + } + + public int updateGuild(GuildEntry guildEntry) { + String sql = + "UPDATE `guilds` SET " + + "`data`='" + guildEntry.asJson() + "'" + + "WHERE `guildID`='" + guildEntry.getGuildID() + "' AND `roboID`='" + guildEntry.getRoboID() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + return 1; + } + return 0; + } + + public GuildEntry fetchGuild(Guild guild) { + String sql = "SELECT * FROM `guilds` WHERE `guildID`='" + guild.getId() + "';"; + try { + ResultSet rs = database.executeQuery(sql); + if (rs.next()) { + String data = rs.getString("data"); + GuildEntry guildEntry = new Gson().fromJson(data, GuildEntry.class); + cache.put(EntryType.DatabaseGuild, guildEntry); + rs.close(); + return guildEntry; + } else { + rs.close(); + return null; + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + return null; + } + } + + //endregion Guild + //region COMMAND + + public void addCommand(CommandEntry commandEntry) { + String sql = "INSERT INTO `commands` (`commandID`, `guildID`, `data`) " + + "VALUES ('" + + commandEntry.commandID + "', '" + + commandEntry.guildID + "', '" + + commandEntry.asJson() + "'" + + ");"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void removeCommand(CommandEntry commandEntry) { + String sql = "DELETE FROM `commands` WHERE `commandID`='" + commandEntry.getCommandID() + "' AND `guildID`='" + commandEntry.guildID + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void updateCommand(CommandEntry commandEntry) { + String sql = "UPDATE `commands` SET `data`='" + commandEntry.asJson() + "' WHERE `commandID`='" + commandEntry.getCommandID() + "' AND `guildID`='" + commandEntry.guildID + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public CommandEntry fetchCommand(String commandID, String guildID) { + String sql = "SELECT * FROM `commands` WHERE `commandID`='" + commandID + "' AND `guildID`='" + guildID + "';"; + try { + ResultSet rs = database.executeQuery(sql); + if (rs.next()) { + String data = rs.getString("data"); + CommandEntry dbg = new Gson().fromJson(data, CommandEntry.class); + cache.put(EntryType.DatabaseCommand, dbg); + rs.close(); + return dbg; + } else { + rs.close(); + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + + //endregion COMMAND + //region RANK + + public void addRank(RankEntry rankEntry) { + String sql = "INSERT INTO `ranks` (`rankID`, `guildID`, `data`) " + + "VALUES ('" + + rankEntry.rankID + "', '" + + rankEntry.guildID + "', '" + + rankEntry.asJson() + "'" + + ");"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void removeRank(RankEntry rankEntry) { + String sql = "DELETE FROM `ranks` WHERE `rankID`='" + rankEntry.getRankID() + "' AND `guildID`='" + rankEntry.getGuildId() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void updateRank(RankEntry rankEntry) { + String sql = "UPDATE `ranks` SET `data`='" + rankEntry.asJson() + "' WHERE `rankID`='" + rankEntry.getRankID() + "' AND `guildID`='" + rankEntry.getGuildId() + "';"; + try { + database.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public RankEntry fetchRank(String rankID, String guildID) { + String sql = "SELECT * FROM `ranks` WHERE `rankID`='" + rankID + "' AND `guildID`='" + guildID + "';"; + try { + ResultSet rs = database.executeQuery(sql); + if (rs.next()) { + String data = rs.getString("data"); + RankEntry dbg = new Gson().fromJson(data, RankEntry.class); + cache.put(EntryType.DatabaseRank, dbg); + rs.close(); + return dbg; + } else { + rs.close(); + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + + //endregion RANK + //region GSON json parsing + + public String convertToJson(Object object) { + Gson gson = new Gson(); + return gson.toJson(object); + } + + public Object convertFromJson(String json, Class classType) { + Gson gson = new Gson(); + return gson.fromJson(json, classType); } + //endregion GSON json parsing } diff --git a/src/main/java/com/devflask/roboflask/database/Guild.java b/src/main/java/com/devflask/roboflask/database/Guild.java deleted file mode 100644 index ded1a4f..0000000 --- a/src/main/java/com/devflask/roboflask/database/Guild.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.devflask.roboflask.database; - -class Guild { - - public Guild(String id){ - - } - -} diff --git a/src/main/java/com/devflask/roboflask/database/Profile.java b/src/main/java/com/devflask/roboflask/database/Profile.java deleted file mode 100644 index 0895182..0000000 --- a/src/main/java/com/devflask/roboflask/database/Profile.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.devflask.roboflask.database; - -class Profile { -} diff --git a/src/main/java/com/devflask/roboflask/database/entry/CommandEntry.java b/src/main/java/com/devflask/roboflask/database/entry/CommandEntry.java new file mode 100644 index 0000000..6677466 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/CommandEntry.java @@ -0,0 +1,125 @@ +package com.devflask.roboflask.database.entry; + +import com.devflask.roboflask.Robo; +import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.database.DatabaseManager; +import com.devflask.roboflask.interfaces.Command; +import com.google.gson.Gson; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +public class CommandEntry implements Command, Entry { + + public String commandID; + public String guildID; + public String name; + public String description; + public String[] arguments; + public String[] instructions; + public String[] roles; + public String[] channels; + public String[] alias; + + public CommandEntry(String commandID, String guildID, String name, String description, String[] arguments, String[] instructions, String[] roles, String[] channels, String[] alias) { + this.commandID = Objects.requireNonNullElseGet(commandID, () -> Robo.generateId() + ""); + this.guildID = guildID; + this.name = name; + this.description = description; + this.arguments = arguments; + this.instructions = instructions; + this.roles = roles; + this.channels = channels; + this.alias = alias; + + DatabaseManager.cache.put(EntryType.DatabaseCommand, this); + } + + //GETTERS + + public String getCommandID() { + return commandID; + } + + public String getGuildID() { + return guildID; + } + + @Override + public @NotNull String getName() { + return this.name; + } + + @Override + public @NotNull String getDescription() { + return this.description; + } + + public @NotNull String[] getArguments() { + return this.arguments; + } + + public @NotNull String[] getInstructions() { + return this.instructions; + } + + public @NotNull String[] getRoles() { + return this.roles; + } + + public @NotNull String[] getChannels() { + return this.channels; + } + + @Override + public @NotNull Collection getAlias() { + return Arrays.asList(alias); + } + + //SETTERS + + public CommandEntry setName(String name) { + this.name = name; + return this; + } + + public CommandEntry setDescription(String description) { + this.description = description; + return this; + } + + public CommandEntry setArguments(String[] arguments) { + this.arguments = arguments; + return this; + } + + public CommandEntry setInstructions(String[] instructions) { + this.instructions = instructions; + return this; + } + + public CommandEntry setRoles(String[] roles) { + this.roles = roles; + return this; + } + + public CommandEntry setChannels(String[] channels) { + this.channels = channels; + return this; + } + + public CommandEntry setAlias(String[] alias) { + this.alias = alias; + return this; + } + + + @Override + public void execute(CommandInformation info) { + //from arguments and instructions + } + + public String asJson() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/devflask/roboflask/database/entry/Entry.java b/src/main/java/com/devflask/roboflask/database/entry/Entry.java new file mode 100644 index 0000000..378e9f4 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/Entry.java @@ -0,0 +1,9 @@ +package com.devflask.roboflask.database.entry; + +import com.google.gson.Gson; + +public interface Entry { + default String asJson() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/devflask/roboflask/database/entry/EntryType.java b/src/main/java/com/devflask/roboflask/database/entry/EntryType.java new file mode 100644 index 0000000..4e4f705 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/EntryType.java @@ -0,0 +1,8 @@ +package com.devflask.roboflask.database.entry; + +public enum EntryType { + DatabaseCommand, + DatabaseRank, + DatabaseProfile, + DatabaseGuild +} diff --git a/src/main/java/com/devflask/roboflask/database/entry/GuildEntry.java b/src/main/java/com/devflask/roboflask/database/entry/GuildEntry.java new file mode 100644 index 0000000..cdd57c8 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/GuildEntry.java @@ -0,0 +1,77 @@ +package com.devflask.roboflask.database.entry; + +import com.devflask.roboflask.database.DatabaseManager; + +public class GuildEntry implements Entry{ + + public String guildID; + public String roboID; + public String prefix; + public CommandEntry[] commands; + public RankEntry[] ranks; + public int totalCommands; + public int totalMessages; + + public GuildEntry(String guildID, String roboID, String prefix, CommandEntry[] commands, RankEntry[] ranks, int totalCommands, int totalMessages) { + this.guildID = guildID; + this.prefix = prefix; + this.commands = commands; + this.ranks = ranks; + this.totalCommands = totalCommands; + this.totalMessages = totalMessages; + + DatabaseManager.cache.put(EntryType.DatabaseGuild, this); + } + + public String getGuildID() { + return guildID; + } + + public String getRoboID() { + return roboID; + } + + public String getPrefix() { + return prefix; + } + + public CommandEntry[] getCommands() { + return commands; + } + + public RankEntry[] getRanks() { + return ranks; + } + + public int getTotalCommands() { + return totalCommands; + } + + public int getTotalMessages() { + return totalMessages; + } + + + //SETTERS + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public void setCommands(CommandEntry[] commands) { + this.commands = commands; + } + + public void setRanks(RankEntry[] ranks) { + this.ranks = ranks; + } + + public void setTotalCommands(int totalCommands) { + this.totalCommands = totalCommands; + } + + public void setTotalMessages(int totalMessages) { + this.totalMessages = totalMessages; + } + + +} diff --git a/src/main/java/com/devflask/roboflask/database/entry/ProfileEntry.java b/src/main/java/com/devflask/roboflask/database/entry/ProfileEntry.java new file mode 100644 index 0000000..19d7d64 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/ProfileEntry.java @@ -0,0 +1,105 @@ +package com.devflask.roboflask.database.entry; + +import net.dv8tion.jda.api.entities.Member; + +public class ProfileEntry implements Entry{ + + private final Member member; + + //stats + private int level; + private int xp; + private int xpToNextLevel; + private int coins; + private int messages; + + //statics + private String profileBanner; + private String profileBorder; + private int profileColor; + + // private Reward[] rewards; + + public ProfileEntry(Member member, int level, int xp, int xpToNextLevel, int coins, int messages, String profileBanner, String profileBorder, int profileColor) { + this.member = member; + this.level = level; + this.xp = xp; + this.xpToNextLevel = xpToNextLevel; + this.coins = coins; + this.messages = messages; + this.profileBanner = profileBanner; + this.profileBorder = profileBorder; + this.profileColor = profileColor; + } + + public Member getMember() { + return member; + } + + public int getLevel() { + return level; + } + + public int getXp() { + return xp; + } + + public int getXpToNextLevel() { + return xpToNextLevel; + } + + public int getCoins() { + return coins; + } + + public int getMessages() { + return messages; + } + + public String getProfileBanner() { + return profileBanner; + } + + public String getProfileBorder() { + return profileBorder; + } + + public int getProfileColor() { + return profileColor; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setXp(int xp) { + this.xp = xp; + } + + public void setXpToNextLevel(int xpToNextLevel) { + this.xpToNextLevel = xpToNextLevel; + } + + public void setCoins(int coins) { + this.coins = coins; + } + + public void setMessages(int messages) { + this.messages = messages; + } + + public void setProfileBanner(String profileBanner) { + this.profileBanner = profileBanner; + } + + public void setProfileBorder(String profileBorder) { + this.profileBorder = profileBorder; + } + + public void setProfileColor(int profileColor) { + this.profileColor = profileColor; + } + + // public void addReward(Reward reward) { + +} diff --git a/src/main/java/com/devflask/roboflask/database/entry/RankEntry.java b/src/main/java/com/devflask/roboflask/database/entry/RankEntry.java new file mode 100644 index 0000000..4e9a641 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/database/entry/RankEntry.java @@ -0,0 +1,65 @@ +package com.devflask.roboflask.database.entry; + +import com.devflask.roboflask.Robo; +import com.devflask.roboflask.database.DatabaseManager; +import com.devflask.roboflask.interfaces.Rank; +import com.google.gson.Gson; +import org.jetbrains.annotations.NotNull; + +public class RankEntry implements Rank, Entry{ + + public String rankID; + public String guildID; + public String name; + public String description; + public String icon; + public int ladderPosition; + + public RankEntry(String rankID, String guildID, String name, String description, String icon, int ladderPosition) { + if (rankID == null) { + this.rankID = Robo.generateId()+""; + }else { + this.rankID = rankID; + } + this.guildID = guildID; + this.name = name; + this.description = description; + this.icon = icon; + this.ladderPosition = ladderPosition; + + DatabaseManager.cache.put(EntryType.DatabaseRank, this); + } + + public String getRankID() { + return this.rankID; + } + + @Override + public @NotNull String getGuildId() { + return this.guildID; + } + + @Override + public @NotNull String getName() { + return this.name; + } + + @Override + public @NotNull String getDescription() { + return this.description; + } + + @Override + public @NotNull String getIcon() { + return this.icon; + } + + @Override + public @NotNull int getLadderPosition() { + return this.ladderPosition; + } + + public String asJson() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/devflask/roboflask/command/Command.java b/src/main/java/com/devflask/roboflask/interfaces/Command.java similarity index 78% rename from src/main/java/com/devflask/roboflask/command/Command.java rename to src/main/java/com/devflask/roboflask/interfaces/Command.java index bad5d7c..4158e57 100644 --- a/src/main/java/com/devflask/roboflask/command/Command.java +++ b/src/main/java/com/devflask/roboflask/interfaces/Command.java @@ -1,6 +1,8 @@ -package com.devflask.roboflask.command; +package com.devflask.roboflask.interfaces; import com.devflask.roboflask.Bot; +import com.devflask.roboflask.command.CommandInformation; +import com.devflask.roboflask.command.CommandManager; import net.dv8tion.jda.api.Permission; import org.jetbrains.annotations.NotNull; @@ -21,8 +23,9 @@ default CommandManager getManager() { default Collection getAlias() { return new HashSet<>(); } + @NotNull - default String getHelp() { + default String getDescription() { return "No help found for this command."; } diff --git a/src/main/java/com/devflask/roboflask/interfaces/Rank.java b/src/main/java/com/devflask/roboflask/interfaces/Rank.java new file mode 100644 index 0000000..656d339 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/interfaces/Rank.java @@ -0,0 +1,17 @@ +package com.devflask.roboflask.interfaces; + +import org.jetbrains.annotations.NotNull; + +public interface Rank { + + @NotNull String getGuildId(); + + @NotNull String getName(); + + @NotNull String getDescription(); + + @NotNull String getIcon(); + + @NotNull int getLadderPosition(); + +} diff --git a/src/main/java/com/devflask/roboflask/modules/ReactionModule.java b/src/main/java/com/devflask/roboflask/modules/ReactionModule.java new file mode 100644 index 0000000..bb204d6 --- /dev/null +++ b/src/main/java/com/devflask/roboflask/modules/ReactionModule.java @@ -0,0 +1,13 @@ +package com.devflask.roboflask.modules; + +import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +public class ReactionModule extends ListenerAdapter { + + @Override + public void onMessageReactionAdd(MessageReactionAddEvent e) { + + } + +}