From 0e79e5aa05bdc2f7684d72ddd4731245dcedba4f Mon Sep 17 00:00:00 2001 From: Aleksei Date: Fri, 14 Feb 2020 23:56:34 -0500 Subject: [PATCH] Added initial SQLite implementation --- .../exceptions/UnknownParameterException.java | 25 +++++ src/main/java/dev/salmonllama/fsbot/Main.java | 5 +- .../salmonllama/fsbot/config/BotConfig.java | 5 +- .../fsbot/database/DatabaseModel.java | 9 ++ .../fsbot/database/DatabaseProvider.java | 92 +++++++++++++++++++ .../dev/salmonllama/fsbot/database/FSDB.java | 46 ++++++++++ 6 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 src/main/java/dev/salmonllama/exceptions/UnknownParameterException.java create mode 100644 src/main/java/dev/salmonllama/fsbot/database/DatabaseModel.java create mode 100644 src/main/java/dev/salmonllama/fsbot/database/DatabaseProvider.java create mode 100644 src/main/java/dev/salmonllama/fsbot/database/FSDB.java diff --git a/src/main/java/dev/salmonllama/exceptions/UnknownParameterException.java b/src/main/java/dev/salmonllama/exceptions/UnknownParameterException.java new file mode 100644 index 0000000..6803f2e --- /dev/null +++ b/src/main/java/dev/salmonllama/exceptions/UnknownParameterException.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020. Aleksei Gryczewski + * All rights reserved. + */ + +package dev.salmonllama.exceptions; + +import java.sql.SQLException; + +public class UnknownParameterException extends SQLException { + private String message; + + public UnknownParameterException(Object param) { + message = "Unknown parameter type: " + param; + } + + public UnknownParameterException(Object param, int index) { + message = String.format("Unknown parameter type %s at %d", param, index); + } + + @Override + public String toString() { + return message; + } +} diff --git a/src/main/java/dev/salmonllama/fsbot/Main.java b/src/main/java/dev/salmonllama/fsbot/Main.java index cc9251b..78d7923 100644 --- a/src/main/java/dev/salmonllama/fsbot/Main.java +++ b/src/main/java/dev/salmonllama/fsbot/Main.java @@ -8,6 +8,7 @@ package dev.salmonllama.fsbot; import com.rethinkdb.RethinkDB; import com.rethinkdb.net.Connection; import dev.salmonllama.fsbot.config.BotConfig; +import dev.salmonllama.fsbot.database.FSDB; import dev.salmonllama.fsbot.guthix.Guthix; import dev.salmonllama.fsbot.listeners.*; import org.javacord.api.DiscordApiBuilder; @@ -25,9 +26,11 @@ public class Main { String configLocation = Constants.BOT_FOLDER.concat(Constants.CONFIG_NAME); BotConfig.initConfig(configLocation); + FSDB.init(); + // Initialise the database with values from the bot's config file RethinkDB r = RethinkDB.r; - Connection conn = r.connection().hostname(BotConfig.DB_HOST).port(BotConfig.DB_PORT).connect(); + Connection conn = r.connection().hostname("localhost").port(28015).connect(); new DiscordApiBuilder().setToken(BotConfig.TOKEN).login().thenAccept(api -> { DatabaseUtilities db = new DatabaseUtilities(r, conn, api); diff --git a/src/main/java/dev/salmonllama/fsbot/config/BotConfig.java b/src/main/java/dev/salmonllama/fsbot/config/BotConfig.java index 180e55f..954cb03 100644 --- a/src/main/java/dev/salmonllama/fsbot/config/BotConfig.java +++ b/src/main/java/dev/salmonllama/fsbot/config/BotConfig.java @@ -3,6 +3,7 @@ * All rights reserved. */ +// Shoutout to Kaaz (again) for a kickass config service: https://github.com/Kaaz/ConfigurationBuilder package dev.salmonllama.fsbot.config; import com.kaaz.configuration.ConfigurationBuilder; @@ -15,10 +16,10 @@ public class BotConfig { public static String TOKEN = "token-goes-here"; @ConfigurationOption - public static String DB_HOST = "localhost"; + public static String DB_ADDR = "fsbot.db"; @ConfigurationOption - public static int DB_PORT = 28015; + public static String DB_NAME = "fsbot"; @ConfigurationOption public static String DEFAULT_PREFIX = "~"; diff --git a/src/main/java/dev/salmonllama/fsbot/database/DatabaseModel.java b/src/main/java/dev/salmonllama/fsbot/database/DatabaseModel.java new file mode 100644 index 0000000..41f9ddd --- /dev/null +++ b/src/main/java/dev/salmonllama/fsbot/database/DatabaseModel.java @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020. Aleksei Gryczewski + * All rights reserved. + */ + +package dev.salmonllama.fsbot.database; + +public class DatabaseModel { +} diff --git a/src/main/java/dev/salmonllama/fsbot/database/DatabaseProvider.java b/src/main/java/dev/salmonllama/fsbot/database/DatabaseProvider.java new file mode 100644 index 0000000..463b95f --- /dev/null +++ b/src/main/java/dev/salmonllama/fsbot/database/DatabaseProvider.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020. Aleksei Gryczewski + * All rights reserved. + */ + +// Heavily inspired by Kaaz's Emily database connection: https://github.com/Kaaz/DiscordBot/tree/master/src/main/java/emily/db +package dev.salmonllama.fsbot.database; + +import dev.salmonllama.exceptions.UnknownParameterException; +import dev.salmonllama.fsbot.config.BotConfig; +import dev.salmonllama.fsbot.utilities.Constants; +import org.sqlite.javax.SQLiteConnectionPoolDataSource; + +import java.sql.*; + +public class DatabaseProvider { + private final String DB_ADDR; + private final String DB_NAME; + private Connection c; + + public DatabaseProvider(String dbName) { + DB_NAME = dbName; + DB_ADDR = "jdbc:sqlite:".concat(Constants.BOT_FOLDER).concat(BotConfig.DB_ADDR); + } + + private Connection createConnection() { + try { + SQLiteConnectionPoolDataSource dataSource = new SQLiteConnectionPoolDataSource(); + dataSource.setDatabaseName(DB_NAME); + dataSource.setUrl(DB_ADDR); + return dataSource.getConnection(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Could not connect to database, double check config values"); + System.exit(1); + } + return null; + } + + public Connection getConnection() { + if (c == null) { + return createConnection(); + } + return c; + } + + private void resolveParameters(PreparedStatement query, Object... params) throws SQLException { + int index = 1; + for (Object p : params) { + if (p instanceof String) { + query.setString(index, (String) p); + } + else if (p instanceof Boolean) { + query.setBoolean(index, (boolean) p); + } + else if (p instanceof Timestamp) { + query.setTimestamp(index, (Timestamp) p); + } else { + throw new UnknownParameterException(p, index); + } + index++; + } + } + + public int query(String sql) throws SQLException { + try (Statement stmt = getConnection().createStatement()) { + return stmt.executeUpdate(sql); + } + } + + public int insert(String sql, Object... params) throws SQLException { + try (PreparedStatement query = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + resolveParameters(query, params); + query.executeUpdate(); + + ResultSet rs = query.getGeneratedKeys(); + + if (rs.next()) { + return rs.getInt(1); + } + + return -1; + } + } + + public ResultSet select(String sql, Object... params) throws SQLException { + PreparedStatement query; + query = getConnection().prepareStatement(sql); + resolveParameters(query, params); + return query.executeQuery(); + } +} diff --git a/src/main/java/dev/salmonllama/fsbot/database/FSDB.java b/src/main/java/dev/salmonllama/fsbot/database/FSDB.java new file mode 100644 index 0000000..866cce9 --- /dev/null +++ b/src/main/java/dev/salmonllama/fsbot/database/FSDB.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020. Aleksei Gryczewski + * All rights reserved. + */ + +// Heavily inspired by Kaaz's Emily database connection: https://github.com/Kaaz/DiscordBot/tree/master/src/main/java/emily/db +package dev.salmonllama.fsbot.database; + +import dev.salmonllama.fsbot.config.BotConfig; +import dev.salmonllama.fsbot.database.models.OutfitModel; + +import java.sql.SQLException; +import java.util.HashMap; + +public class FSDB { + private static final String DEFAULT_CONNECTION = "fsbot"; + private static final HashMap connections = new HashMap<>(); + + public static DatabaseProvider get(String key) { + if (connections.containsKey(key)) { + return connections.get(key); + } + + System.out.println(String.format("Specified connection %s has not been set.", key)); + return null; + } + + public static DatabaseProvider get() { + return connections.get(DEFAULT_CONNECTION); + } + + public static void init() { + connections.clear(); + connections.put(DEFAULT_CONNECTION, new DatabaseProvider(BotConfig.DB_NAME)); + + prepareTables(); + } + + private static void prepareTables() { + try { + get().query(OutfitModel.schema()); + } catch (SQLException e) { + e.printStackTrace(); + } + } +}