jcenter
@@ -156,20 +148,61 @@
3.0.1.RELEASE
compile
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+ compile
+
+ DisCal
+
+ clean package
org.apache.maven.plugins
maven-compiler-plugin
3.7.0
- 8
- 8
- UTF-8
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+
+ true
+ com.cloudcraftgaming.discal.Main
+
+
+
+
+ src/main/resources
+ true
+
+
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/Main.java b/src/main/java/com/cloudcraftgaming/discal/Main.java
new file mode 100644
index 00000000..048dc1cf
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/Main.java
@@ -0,0 +1,106 @@
+package com.cloudcraftgaming.discal;
+
+import com.cloudcraftgaming.discal.api.DisCalAPI;
+import com.cloudcraftgaming.discal.api.database.DatabaseManager;
+import com.cloudcraftgaming.discal.api.message.MessageManager;
+import com.cloudcraftgaming.discal.api.network.google.Authorization;
+import com.cloudcraftgaming.discal.api.object.BotSettings;
+import com.cloudcraftgaming.discal.bot.internal.consolecommand.ConsoleCommandExecutor;
+import com.cloudcraftgaming.discal.bot.listeners.ReadyEventListener;
+import com.cloudcraftgaming.discal.bot.module.command.*;
+import com.cloudcraftgaming.discal.logger.Logger;
+import com.cloudcraftgaming.discal.web.handler.DiscordAccountHandler;
+import com.cloudcraftgaming.discal.web.utils.SparkUtils;
+import sx.blah.discord.api.ClientBuilder;
+import sx.blah.discord.api.IDiscordClient;
+import sx.blah.discord.api.events.EventDispatcher;
+import sx.blah.discord.util.DiscordException;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Created by Nova Fox on 1/2/2017.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal
+ */
+@SuppressWarnings("ThrowableNotThrown")
+public class Main {
+ public static String version = "2.0.0";
+
+ public static void main(String[] args) throws IOException {
+ //Get bot settings
+ Properties p = new Properties();
+ p.load(new FileReader(new File("settings.properties")));
+ BotSettings.init(p);
+
+ //Init logger
+ Logger.getLogger().init();
+
+ //Log in to discord
+ DisCalAPI api = DisCalAPI.getAPI();
+
+ api.init(createClient(BotSettings.TOKEN.get()));
+ if (api.getClient() == null)
+ throw new NullPointerException("Failed to build! Client cannot be null!");
+
+ //Register events
+ EventDispatcher dispatcher = api.getClient().getDispatcher();
+ dispatcher.registerListener(new ReadyEventListener());
+
+ api.getClient().login();
+
+ Authorization.getAuth().init();
+
+ //Connect to MySQL
+ DatabaseManager.getManager().connectToMySQL();
+ DatabaseManager.getManager().createTables();
+
+ //Start spark (catch any issues from it so only the site goes down without affecting bot....
+ try {
+ DiscordAccountHandler.getHandler().init();
+ SparkUtils.initSpark();
+ } catch (Exception e) {
+ Logger.getLogger().exception(null, "'Spark ERROR' by 'PANIC! AT THE WEBSITE'", e, Main.class, true);
+ }
+
+ //Register modules
+ CommandExecutor executor = CommandExecutor.getExecutor().enable();
+ executor.registerCommand(new HelpCommand());
+ executor.registerCommand(new DisCalCommand());
+ executor.registerCommand(new CalendarCommand());
+ executor.registerCommand(new AddCalendarCommand());
+ executor.registerCommand(new LinkCalendarCommand());
+ executor.registerCommand(new TimeCommand());
+ executor.registerCommand(new EventListCommand());
+ executor.registerCommand(new EventCommand());
+ executor.registerCommand(new RsvpCommand());
+ executor.registerCommand(new AnnouncementCommand());
+ executor.registerCommand(new DevCommand());
+
+ //Load language files.
+ MessageManager.loadLangs();
+
+ //Accept commands
+ ConsoleCommandExecutor.init();
+ }
+
+ /**
+ * Creates the DisCal bot client.
+ *
+ * @param token The Bot Token.
+ * @return The client if successful, otherwise null.
+ */
+ private static IDiscordClient createClient(String token) {
+ ClientBuilder clientBuilder = new ClientBuilder();
+ clientBuilder.withToken(token).withRecommendedShardCount();
+ try {
+ return clientBuilder.build();
+ } catch (DiscordException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/DisCalAPI.java b/src/main/java/com/cloudcraftgaming/discal/api/DisCalAPI.java
new file mode 100644
index 00000000..f9bbcb66
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/DisCalAPI.java
@@ -0,0 +1,37 @@
+package com.cloudcraftgaming.discal.api;
+
+import sx.blah.discord.api.IDiscordClient;
+
+public class DisCalAPI {
+ private static DisCalAPI instance;
+
+ private static IDiscordClient client;
+
+ //final global variables.
+ public String iconUrl;
+ public final long novaId = 130510525770629121L;
+ public final long xaanitId = 233611560545812480L;
+ public final long calId = 142107863307780097L;
+ public final long dreamId = 282662248365817867L;
+
+ public final long errorLog = 459411923935690752L;
+ public final long serverId = 375357265198317579L;
+
+ private DisCalAPI() {
+ }
+
+ public static DisCalAPI getAPI() {
+ if (instance == null)
+ instance = new DisCalAPI();
+
+ return instance;
+ }
+
+ public void init(IDiscordClient _client) {
+ client = _client;
+ }
+
+ public IDiscordClient getClient() {
+ return client;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/calendar/CalendarAuth.java b/src/main/java/com/cloudcraftgaming/discal/api/calendar/CalendarAuth.java
new file mode 100644
index 00000000..6375d33d
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/calendar/CalendarAuth.java
@@ -0,0 +1,120 @@
+package com.cloudcraftgaming.discal.api.calendar;
+
+import com.cloudcraftgaming.discal.api.crypto.AESEncryption;
+import com.cloudcraftgaming.discal.api.network.google.Authorization;
+import com.cloudcraftgaming.discal.api.object.GuildSettings;
+import com.cloudcraftgaming.discal.logger.Logger;
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
+import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
+import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
+import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
+import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.client.util.store.FileDataStoreFactory;
+import com.google.api.services.calendar.CalendarScopes;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
+public class CalendarAuth {
+ /**
+ * Application name.
+ */
+ private static final String APPLICATION_NAME = "DisCal";
+
+ /**
+ * Directory to store user credentials for this application.
+ */
+ private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/DisCal");
+
+ /**
+ * Global instance of the {@link FileDataStoreFactory}.
+ */
+ private static FileDataStoreFactory DATA_STORE_FACTORY;
+
+ /**
+ * Global instance of the JSON factory.
+ */
+ private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
+
+ /**
+ * Global instance of the HTTP transport.
+ */
+ private static HttpTransport HTTP_TRANSPORT;
+
+ /**
+ * Global instance of the scopes required by this quickstart.
+ *
+ * If modifying these scopes, delete your previously saved credentials
+ * at ~/.credentials/calendar-java-quickstart
+ */
+ private static final List SCOPES = Arrays.asList(CalendarScopes.CALENDAR);
+
+ static {
+ try {
+ HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
+ DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Creates an authorized Credential object.
+ *
+ * @return an authorized Credential object.
+ * @throws IOException In the event authorization fails.
+ */
+ private static Credential authorize() throws IOException {
+ // Load client secrets.
+ //InputStream in = CalendarAuth.class.getResourceAsStream("/client_secret.json"); <- incase it breaks, this is still here
+ InputStream in = new FileInputStream(new File("client_secret.json"));
+ GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
+
+ // Build flow and trigger user authorization request.
+ GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
+ Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
+ Logger.getLogger().debug("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
+
+ //Try to close input stream since I don't think it was ever closed?
+ in.close();
+
+ return credential;
+ }
+
+ private static Credential authorize(GuildSettings g) throws Exception {
+ if (g.getEncryptedAccessToken().equalsIgnoreCase("N/a"))
+ throw new IllegalAccessException("Guild does not have proper access token!");
+
+
+ AESEncryption encryption = new AESEncryption(g);
+ String accessToken = Authorization.getAuth().requestNewAccessToken(g, encryption);
+
+ GoogleCredential credential = new GoogleCredential();
+ credential.setAccessToken(accessToken);
+ return credential;
+ }
+
+ public static com.google.api.services.calendar.Calendar getCalendarService(GuildSettings g) throws Exception {
+ if (g != null && g.useExternalCalendar()) {
+ Credential credential = authorize(g);
+ return new com.google.api.services.calendar.Calendar.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential).setApplicationName(APPLICATION_NAME).build();
+ } else {
+ Credential credential = authorize();
+ return new com.google.api.services.calendar.Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/crypto/AESEncryption.java b/src/main/java/com/cloudcraftgaming/discal/api/crypto/AESEncryption.java
new file mode 100644
index 00000000..7a2e9e79
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/crypto/AESEncryption.java
@@ -0,0 +1,66 @@
+package com.cloudcraftgaming.discal.api.crypto;
+
+import com.cloudcraftgaming.discal.api.object.GuildSettings;
+import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings("SpellCheckingInspection")
+public class AESEncryption {
+ //Public key, its fine if this is here, I don't even have access to private keys
+ private static final String SECRET_KEY_1 = "E4B39r8F57F1Csde";
+
+ private IvParameterSpec ivParameterSpec;
+ private SecretKeySpec secretKeySpec;
+ private Cipher cipher;
+
+ /**
+ * Constructor for AESEncryption.
+ * This class it to be used for encrypting/decrypting data.
+ *
+ * @throws Exception if something fails
+ */
+ public AESEncryption(GuildSettings gs) throws Exception {
+ String SECRET_KEY_2 = gs.getPrivateKey();
+ ivParameterSpec = new IvParameterSpec(SECRET_KEY_1.getBytes(StandardCharsets.UTF_8));
+ secretKeySpec = new SecretKeySpec(SECRET_KEY_2.getBytes(StandardCharsets.UTF_8), "AES");
+ cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
+ }
+
+ /**
+ * Encrypt the Data with the secret key.
+ * **WARNING** Can only be decrypted by this class!!!
+ *
+ * @param data The data to encrypt.
+ * @return The encrypted, unreadable data.
+ * @throws Exception If something fails.
+ */
+ public String encrypt(String data) throws Exception {
+ cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
+ byte[] encrypted = cipher.doFinal(data.getBytes());
+ return Base64.encodeBase64String(encrypted);
+ }
+
+ /**
+ * Decrypt the Data with the secret key.
+ * **WARNING** Can only be encrypted with this class!!!
+ * **WARNING** Decrypting of data can be a security risk! Treat with care!!
+ *
+ * @param encryptedData The data to decrypt.
+ * @return The data, decrypted.
+ * @throws Exception If something fails.
+ */
+ public String decrypt(String encryptedData) throws Exception {
+ cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
+ byte[] decryptedBytes = cipher.doFinal(Base64.decodeBase64(encryptedData));
+ return new String(decryptedBytes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/crypto/KeyGenerator.java b/src/main/java/com/cloudcraftgaming/discal/api/crypto/KeyGenerator.java
new file mode 100644
index 00000000..ed3e8ecb
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/crypto/KeyGenerator.java
@@ -0,0 +1,62 @@
+package com.cloudcraftgaming.discal.api.crypto;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+public class KeyGenerator {
+ private static char[] VALID_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456879".toCharArray();
+
+ private static char[] VALID_CHARS_2 = "abcdefghijklmnopqrstuv0123456789".toCharArray();
+
+ // cs = cryptographically secure
+ @SuppressWarnings("SameParameterValue")
+ public static String csRandomAlphaNumericString(int numChars) {
+ SecureRandom secRand = new SecureRandom();
+ Random rand = new Random();
+ char[] buff = new char[numChars];
+
+ for (int i = 0; i < numChars; ++i) {
+ // reseed rand once you've used up all available entropy bits
+ if ((i % 10) == 0)
+ rand.setSeed(secRand.nextLong()); // 64 bits of random!
+
+ buff[i] = VALID_CHARACTERS[rand.nextInt(VALID_CHARACTERS.length)];
+ }
+ return new String(buff);
+ }
+
+ public static String generateEventId() {
+ SecureRandom secRand = new SecureRandom();
+ Random rand = new Random();
+ char[] buff = new char[9];
+
+ for (int i = 0; i < 9; ++i) {
+ // reseed rand once you've used up all available entropy bits
+ if ((i % 10) == 0)
+ rand.setSeed(secRand.nextLong()); // 64 bits of random!
+
+ buff[i] = VALID_CHARS_2[rand.nextInt(VALID_CHARS_2.length)];
+ }
+ return "e" + new String(buff);
+ }
+
+ public static String generateAnnouncementId() {
+ SecureRandom secRand = new SecureRandom();
+ Random rand = new Random();
+ char[] buff = new char[9];
+
+ for (int i = 0; i < 9; ++i) {
+ // reseed rand once you've used up all available entropy bits
+ if ((i % 10) == 0)
+ rand.setSeed(secRand.nextLong()); // 64 bits of random!
+
+ buff[i] = VALID_CHARS_2[rand.nextInt(VALID_CHARS_2.length)];
+ }
+ return "a" + new String(buff);
+ }
+}
\ No newline at end of file
diff --git a/API/src/main/java/com/cloudcraftgaming/discal/api/database/Database.java b/src/main/java/com/cloudcraftgaming/discal/api/database/Database.java
similarity index 100%
rename from API/src/main/java/com/cloudcraftgaming/discal/api/database/Database.java
rename to src/main/java/com/cloudcraftgaming/discal/api/database/Database.java
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseInfo.java b/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseInfo.java
new file mode 100644
index 00000000..477f1ec5
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseInfo.java
@@ -0,0 +1,55 @@
+package com.cloudcraftgaming.discal.api.database;
+
+import java.sql.Connection;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings("unused")
+class DatabaseInfo {
+ private MySQL mySQL;
+ private Connection con;
+ private String prefix;
+
+ /**
+ * Creates a new DatabaseInfo Object
+ *
+ * @param _mySQL The MySQL server element.
+ * @param _con The connection to the MySQL server.
+ * @param _prefix The prefix for all tables.
+ */
+ DatabaseInfo(MySQL _mySQL, Connection _con, String _prefix) {
+ mySQL = _mySQL;
+ con = _con;
+ prefix = _prefix;
+ }
+
+ /**
+ * Gets the MySQL server currently connected
+ *
+ * @return The MySQL server currently connect.
+ */
+ MySQL getMySQL() {
+ return mySQL;
+ }
+
+ /**
+ * Gets the current connection to the MySQL server.
+ *
+ * @return The current connection to the MySQL server.
+ */
+ Connection getConnection() {
+ return con;
+ }
+
+ /**
+ * Gets the prefix for all tables.
+ *
+ * @return The prefix for all tables.
+ */
+ String getPrefix() {
+ return prefix;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseManager.java b/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseManager.java
new file mode 100644
index 00000000..b5360ab2
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/database/DatabaseManager.java
@@ -0,0 +1,1315 @@
+package com.cloudcraftgaming.discal.api.database;
+
+import com.cloudcraftgaming.discal.api.crypto.KeyGenerator;
+import com.cloudcraftgaming.discal.api.enums.announcement.AnnouncementType;
+import com.cloudcraftgaming.discal.api.enums.event.EventColor;
+import com.cloudcraftgaming.discal.api.object.BotSettings;
+import com.cloudcraftgaming.discal.api.object.GuildSettings;
+import com.cloudcraftgaming.discal.api.object.announcement.Announcement;
+import com.cloudcraftgaming.discal.api.object.calendar.CalendarData;
+import com.cloudcraftgaming.discal.api.object.event.EventData;
+import com.cloudcraftgaming.discal.api.object.event.RsvpData;
+import com.cloudcraftgaming.discal.api.object.web.UserAPIAccount;
+import com.cloudcraftgaming.discal.logger.Logger;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.UUID;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings({"SqlResolve", "UnusedReturnValue", "SqlNoDataSourceInspection", "Duplicates"})
+public class DatabaseManager {
+ private static DatabaseManager instance;
+ private DatabaseInfo databaseInfo;
+
+ private DatabaseManager() {
+ } //Prevent initialization.
+
+ /**
+ * Gets the instance of the {@link DatabaseManager}.
+ *
+ * @return The instance of the {@link DatabaseManager}
+ */
+ public static DatabaseManager getManager() {
+ if (instance == null)
+ instance = new DatabaseManager();
+
+ return instance;
+ }
+
+ /**
+ * Connects to the MySQL server specified.
+ */
+ public void connectToMySQL() {
+ try {
+ MySQL mySQL = new MySQL(BotSettings.SQL_HOST.get(), BotSettings.SQL_PORT.get(), BotSettings.SQL_DB.get(), BotSettings.SQL_PREFIX.get(), BotSettings.SQL_USER.get(), BotSettings.SQL_PASSWORD.get());
+
+ Connection mySQLConnection = mySQL.openConnection();
+ databaseInfo = new DatabaseInfo(mySQL, mySQLConnection, mySQL.getPrefix());
+ System.out.println("Connected to MySQL database!");
+ } catch (Exception e) {
+ System.out.println("Failed to connect to MySQL database! Is it properly configured?");
+ e.printStackTrace();
+ Logger.getLogger().exception(null, "Connecting to MySQL server failed.", e, this.getClass(), true);
+ }
+ }
+
+ /**
+ * Disconnects from the MySQL server if still connected.
+ */
+ public void disconnectFromMySQL() {
+ if (databaseInfo != null) {
+ try {
+ databaseInfo.getMySQL().closeConnection();
+ System.out.println("Successfully disconnected from MySQL Database!");
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Disconnecting from MySQL failed.", e, this.getClass(), true);
+ System.out.println("MySQL Connection may not have closed properly! Data may be invalidated!");
+ }
+ }
+ }
+
+ /**
+ * Creates all required tables in the database if they do not exist.
+ */
+ public void createTables() {
+ try {
+ Statement statement = databaseInfo.getConnection().createStatement();
+
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+ String settingsTableName = String.format("%sguild_settings", databaseInfo.getPrefix());
+ String eventTableName = String.format("%sevents", databaseInfo.getPrefix());
+ String rsvpTableName = String.format("%srsvp", databaseInfo.getPrefix());
+ String apiTableName = String.format("%sapi", databaseInfo.getPrefix());
+ String createSettingsTable = "CREATE TABLE IF NOT EXISTS " + settingsTableName +
+ "(GUILD_ID VARCHAR(255) not NULL, " +
+ " EXTERNAL_CALENDAR BOOLEAN not NULL, " +
+ " PRIVATE_KEY VARCHAR(16) not NULL, " +
+ " ACCESS_TOKEN LONGTEXT not NULL, " +
+ " REFRESH_TOKEN LONGTEXT not NULL, " +
+ " CONTROL_ROLE LONGTEXT not NULL, " +
+ " DISCAL_CHANNEL LONGTEXT not NULL, " +
+ " SIMPLE_ANNOUNCEMENT BOOLEAN not NULL, " +
+ " LANG VARCHAR(255) not NULL, " +
+ " PREFIX VARCHAR(255) not NULL, " +
+ " PATRON_GUILD BOOLEAN not NULL, " +
+ " DEV_GUILD BOOLEAN not NULL, " +
+ " MAX_CALENDARS INTEGER not NULL, " +
+ " DM_ANNOUNCEMENTS LONGTEXT not NULL, " +
+ " 12_HOUR BOOLEAN not NULL, " +
+ " BRANDED BOOLEAN not NULL, " +
+ " PRIMARY KEY (GUILD_ID))";
+ String createAnnouncementTable = "CREATE TABLE IF NOT EXISTS " + announcementTableName +
+ " (ANNOUNCEMENT_ID VARCHAR(255) not NULL, " +
+ " GUILD_ID VARCHAR(255) not NULL, " +
+ " SUBSCRIBERS_ROLE LONGTEXT not NULL, " +
+ " SUBSCRIBERS_USER LONGTEXT not NULL, " +
+ " CHANNEL_ID VARCHAR(255) not NULL, " +
+ " ANNOUNCEMENT_TYPE VARCHAR(255) not NULL, " +
+ " EVENT_ID LONGTEXT not NULL, " +
+ " EVENT_COLOR VARCHAR(255) not NULL, " +
+ " HOURS_BEFORE INTEGER not NULL, " +
+ " MINUTES_BEFORE INTEGER not NULL, " +
+ " INFO LONGTEXT not NULL, " +
+ " ENABLED BOOLEAN not NULL, " +
+ " INFO_ONLY BOOLEAN not NULL, " +
+ " PRIMARY KEY (ANNOUNCEMENT_ID))";
+ String createCalendarTable = "CREATE TABLE IF NOT EXISTS " + calendarTableName +
+ " (GUILD_ID VARCHAR(255) not NULL, " +
+ " CALENDAR_NUMBER INTEGER not NULL, " +
+ " CALENDAR_ID VARCHAR(255) not NULL, " +
+ " CALENDAR_ADDRESS LONGTEXT not NULL, " +
+ " EXTERNAL BOOLEAN not NULL , " +
+ " PRIMARY KEY (GUILD_ID, CALENDAR_NUMBER))";
+ String createEventTable = "CREATE TABLE IF NOT EXISTS " + eventTableName +
+ " (GUILD_ID VARCHAR(255) not NULL, " +
+ " EVENT_ID VARCHAR(255) not NULL, " +
+ " EVENT_END LONG not NULL, " +
+ " IMAGE_LINK LONGTEXT, " +
+ " PRIMARY KEY (GUILD_ID, EVENT_ID))";
+ String createRsvpTable = "CREATE TABLE IF NOT EXISTS " + rsvpTableName +
+ " (GUILD_ID VARCHAR(255) not NULL, " +
+ " EVENT_ID VARCHAR(255) not NULL, " +
+ " EVENT_END LONG not NULL, " +
+ " GOING_ON_TIME LONGTEXT, " +
+ " GOING_LATE LONGTEXT, " +
+ " NOT_GOING LONGTEXT, " +
+ " UNDECIDED LONGTEXT, " +
+ " PRIMARY KEY (GUILD_ID, EVENT_ID))";
+ String createAPITable = "CREATE TABLE IF NOT EXISTS " + apiTableName +
+ " (USER_ID varchar(255) not NULL, " +
+ " API_KEY varchar(64) not NULL, " +
+ " BLOCKED BOOLEAN not NULL, " +
+ " TIME_ISSUED LONG not NULL, " +
+ " USES INT not NULL, " +
+ " PRIMARY KEY (USER_ID, API_KEY))";
+ statement.executeUpdate(createAnnouncementTable);
+ statement.executeUpdate(createSettingsTable);
+ statement.executeUpdate(createCalendarTable);
+ statement.executeUpdate(createEventTable);
+ statement.executeUpdate(createRsvpTable);
+ statement.executeUpdate(createAPITable);
+ statement.close();
+ System.out.println("Successfully created needed tables in MySQL database!");
+ } catch (SQLException e) {
+ System.out.println("Failed to created database tables! Something must be wrong.");
+ Logger.getLogger().exception(null, "Creating MySQL tables failed", e, this.getClass(), true);
+ e.printStackTrace();
+ }
+ }
+
+ public boolean updateAPIAccount(UserAPIAccount acc) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String tableName = String.format("%sapi", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + tableName + " WHERE API_KEY = '" + String.valueOf(acc.getAPIKey()) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("API_KEY") == null) {
+ //Data not present, add to DB.
+ String insertCommand = "INSERT INTO " + tableName +
+ "(USER_ID, API_KEY, BLOCKED, TIME_ISSUED, USES)" +
+ " VALUES (?, ?, ?, ?, ?);";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, acc.getUserId());
+ ps.setString(2, acc.getAPIKey());
+ ps.setBoolean(3, acc.isBlocked());
+ ps.setLong(4, acc.getTimeIssued());
+ ps.setInt(5, acc.getUses());
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+ String update = "UPDATE " + tableName
+ + " SET USER_ID = ?, BLOCKED = ?,"
+ + " USES = ? WHERE API_KEY = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+
+ ps.setString(1, acc.getUserId());
+ ps.setBoolean(2, acc.isBlocked());
+ ps.setInt(3, acc.getUses());
+ ps.setString(4, acc.getAPIKey());
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ Logger.getLogger().exception(null, "Failed to update API account", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean updateSettings(GuildSettings settings) {
+ if (settings.getPrivateKey().equalsIgnoreCase("N/a"))
+ settings.setPrivateKey(KeyGenerator.csRandomAlphaNumericString(16));
+
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String dataTableName = String.format("%sguild_settings", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + dataTableName + " WHERE GUILD_ID = '" + String.valueOf(settings.getGuildID()) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("GUILD_ID") == null) {
+ //Data not present, add to DB.
+ String insertCommand = "INSERT INTO " + dataTableName +
+ "(GUILD_ID, EXTERNAL_CALENDAR, PRIVATE_KEY, ACCESS_TOKEN, REFRESH_TOKEN, CONTROL_ROLE, DISCAL_CHANNEL, SIMPLE_ANNOUNCEMENT, LANG, PREFIX, PATRON_GUILD, DEV_GUILD, MAX_CALENDARS, DM_ANNOUNCEMENTS, 12_HOUR, BRANDED)" +
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, String.valueOf(settings.getGuildID()));
+ ps.setBoolean(2, settings.useExternalCalendar());
+ ps.setString(3, settings.getPrivateKey());
+ ps.setString(4, settings.getEncryptedAccessToken());
+ ps.setString(5, settings.getEncryptedRefreshToken());
+ ps.setString(6, settings.getControlRole());
+ ps.setString(7, settings.getDiscalChannel());
+ ps.setBoolean(8, settings.usingSimpleAnnouncements());
+ ps.setString(9, settings.getLang());
+ ps.setString(10, settings.getPrefix());
+ ps.setBoolean(11, settings.isPatronGuild());
+ ps.setBoolean(12, settings.isDevGuild());
+ ps.setInt(13, settings.getMaxCalendars());
+ ps.setString(14, settings.getDmAnnouncementsString());
+ ps.setBoolean(15, settings.useTwelveHour());
+ ps.setBoolean(16, settings.isBranded());
+
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+ String update = "UPDATE " + dataTableName
+ + " SET EXTERNAL_CALENDAR = ?, PRIVATE_KEY = ?,"
+ + " ACCESS_TOKEN = ?, REFRESH_TOKEN = ?,"
+ + " CONTROL_ROLE = ?, DISCAL_CHANNEL = ?, SIMPLE_ANNOUNCEMENT = ?,"
+ + " LANG = ?, PREFIX = ?, PATRON_GUILD = ?, DEV_GUILD = ?,"
+ + " MAX_CALENDARS = ?, DM_ANNOUNCEMENTS = ?, 12_HOUR = ?,"
+ + " BRANDED = ? WHERE GUILD_ID = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+
+ ps.setBoolean(1, settings.useExternalCalendar());
+ ps.setString(2, settings.getPrivateKey());
+ ps.setString(3, settings.getEncryptedAccessToken());
+ ps.setString(4, settings.getEncryptedRefreshToken());
+ ps.setString(5, settings.getControlRole());
+ ps.setString(6, settings.getDiscalChannel());
+ ps.setBoolean(7, settings.usingSimpleAnnouncements());
+ ps.setString(8, settings.getLang());
+ ps.setString(9, settings.getPrefix());
+ ps.setBoolean(10, settings.isPatronGuild());
+ ps.setBoolean(11, settings.isDevGuild());
+ ps.setInt(12, settings.getMaxCalendars());
+ ps.setString(13, settings.getDmAnnouncementsString());
+ ps.setBoolean(14, settings.useTwelveHour());
+ ps.setBoolean(15, settings.isBranded());
+ ps.setString(16, String.valueOf(settings.getGuildID()));
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ System.out.println("Failed to input data into database! Error Code: 00101");
+ Logger.getLogger().exception(null, "Failed to update/insert guild settings.", e, this.getClass(), true);
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public boolean updateCalendar(CalendarData calData) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = '" + String.valueOf(calData.getGuildId()) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("GUILD_ID") == null) {
+ //Data not present, add to DB.
+ String insertCommand = "INSERT INTO " + calendarTableName +
+ "(GUILD_ID, CALENDAR_NUMBER, CALENDAR_ID, CALENDAR_ADDRESS, EXTERNAL)" +
+ " VALUES (?, ?, ?, ?, ?);";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, String.valueOf(calData.getGuildId()));
+ ps.setInt(2, calData.getCalendarNumber());
+ ps.setString(3, calData.getCalendarId());
+ ps.setString(4, calData.getCalendarAddress());
+ ps.setBoolean(5, calData.isExternal());
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+ String update = "UPDATE " + calendarTableName
+ + " SET CALENDAR_NUMBER = ?, CALENDAR_ID = ?,"
+ + " CALENDAR_ADDRESS = ?, EXTERNAL = ?"
+ + " WHERE GUILD_ID = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+ ps.setInt(1, calData.getCalendarNumber());
+ ps.setString(2, calData.getCalendarId());
+ ps.setString(3, calData.getCalendarAddress());
+ ps.setBoolean(4, calData.isExternal());
+ ps.setString(5, String.valueOf(calData.getGuildId()));
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to update/insert calendar data.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ /**
+ * Updates or Adds the specified {@link Announcement} Object to the database.
+ *
+ * @param announcement The announcement object to add to the database.
+ * @return true if successful, else false.
+ */
+ public boolean updateAnnouncement(Announcement announcement) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = '" + announcement.getAnnouncementId() + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("ANNOUNCEMENT_ID") == null) {
+ //Data not present, add to db.
+ String insertCommand = "INSERT INTO " + announcementTableName +
+ "(ANNOUNCEMENT_ID, GUILD_ID, SUBSCRIBERS_ROLE, SUBSCRIBERS_USER, CHANNEL_ID, ANNOUNCEMENT_TYPE, EVENT_ID, EVENT_COLOR, HOURS_BEFORE, MINUTES_BEFORE, INFO, ENABLED, INFO_ONLY)" +
+ " VALUE (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, announcement.getAnnouncementId().toString());
+ ps.setString(2, String.valueOf(announcement.getGuildId()));
+ ps.setString(3, announcement.getSubscriberRoleIdString());
+ ps.setString(4, announcement.getSubscriberUserIdString());
+ ps.setString(5, announcement.getAnnouncementChannelId());
+ ps.setString(6, announcement.getAnnouncementType().name());
+ ps.setString(7, announcement.getEventId());
+ ps.setString(8, announcement.getEventColor().name());
+ ps.setInt(9, announcement.getHoursBefore());
+ ps.setInt(10, announcement.getMinutesBefore());
+ ps.setString(11, announcement.getInfo());
+ ps.setBoolean(12, announcement.isEnabled());
+ ps.setBoolean(13, announcement.isInfoOnly());
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+
+ String update = "UPDATE " + announcementTableName
+ + " SET SUBSCRIBERS_ROLE = ?, SUBSCRIBERS_USER = ?, CHANNEL_ID = ?,"
+ + " ANNOUNCEMENT_TYPE = ?, EVENT_ID = ?, EVENT_COLOR = ?, "
+ + " HOURS_BEFORE = ?, MINUTES_BEFORE = ?,"
+ + " INFO = ?, ENABLED = ?, INFO_ONLY = ?"
+ + " WHERE ANNOUNCEMENT_ID = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+
+ ps.setString(1, announcement.getSubscriberRoleIdString());
+ ps.setString(2, announcement.getSubscriberUserIdString());
+ ps.setString(3, announcement.getAnnouncementChannelId());
+ ps.setString(4, announcement.getAnnouncementType().name());
+ ps.setString(5, announcement.getEventId());
+ ps.setString(6, announcement.getEventColor().name());
+ ps.setInt(7, announcement.getHoursBefore());
+ ps.setInt(8, announcement.getMinutesBefore());
+ ps.setString(9, announcement.getInfo());
+ ps.setBoolean(10, announcement.isEnabled());
+ ps.setBoolean(11, announcement.isInfoOnly());
+
+ ps.setString(12, announcement.getAnnouncementId().toString());
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ System.out.print("Failed to input announcement data! Error Code: 00201");
+ Logger.getLogger().exception(null, "Failed to update/insert announcement.", e, this.getClass(), true);
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public boolean updateEventData(EventData data) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String eventTableName = String.format("%sevents", databaseInfo.getPrefix());
+
+ if (data.getEventId().contains("_")) {
+ data.setEventId(data.getEventId().split("_")[0]);
+ }
+
+ String query = "SELECT * FROM " + eventTableName + " WHERE EVENT_ID = '" + data.getEventId() + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("EVENT_ID") == null) {
+ //Data not present, add to DB.
+ String insertCommand = "INSERT INTO " + eventTableName +
+ "(GUILD_ID, EVENT_ID, EVENT_END, IMAGE_LINK)" +
+ " VALUES (?, ?, ?, ?)";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, String.valueOf(data.getGuildId()));
+ ps.setString(2, data.getEventId());
+ ps.setLong(3, data.getEventEnd());
+ ps.setString(4, data.getImageLink());
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+ String update = "UPDATE " + eventTableName
+ + " SET IMAGE_LINK = ?, EVENT_END = ?"
+ + " WHERE EVENT_ID = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+
+ ps.setString(1, data.getImageLink());
+ ps.setLong(2, data.getEventEnd());
+ ps.setString(3, data.getEventId());
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to update/insert event data.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean updateRsvpData(RsvpData data) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String rsvpTableName = String.format("%srsvp", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + rsvpTableName + " WHERE EVENT_ID = '" + data.getEventId() + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (!hasStuff || res.getString("EVENT_ID") == null) {
+ //Data not present, add to DB.
+ String insertCommand = "INSERT INTO " + rsvpTableName +
+ "(GUILD_ID, EVENT_ID, EVENT_END, GOING_ON_TIME, GOING_LATE, NOT_GOING, UNDECIDED)" +
+ " VALUES (?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(insertCommand);
+ ps.setString(1, String.valueOf(data.getGuildId()));
+ ps.setString(2, data.getEventId());
+ ps.setLong(3, data.getEventEnd());
+ ps.setString(4, data.getGoingOnTimeString());
+ ps.setString(5, data.getGoingLateString());
+ ps.setString(6, data.getNotGoingString());
+ ps.setString(7, data.getUndecidedString());
+
+ ps.executeUpdate();
+ ps.close();
+ statement.close();
+ } else {
+ //Data present, update.
+ String update = "UPDATE " + rsvpTableName
+ + " SET EVENT_END = ?,"
+ + " GOING_ON_TIME = ?,"
+ + " GOING_LATE = ?,"
+ + " NOT_GOING = ?,"
+ + " UNDECIDED = ?"
+ + " WHERE EVENT_ID = ?";
+ PreparedStatement ps = databaseInfo.getConnection().prepareStatement(update);
+
+ ps.setLong(1, data.getEventEnd());
+ ps.setString(2, data.getGoingOnTimeString());
+ ps.setString(3, data.getGoingLateString());
+ ps.setString(4, data.getNotGoingString());
+ ps.setString(5, data.getUndecidedString());
+ ps.setString(6, data.getEventId());
+
+ ps.executeUpdate();
+
+ ps.close();
+ statement.close();
+ }
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to update/insert event data.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public UserAPIAccount getAPIAccount(String APIKey) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String dataTableName = String.format("%sapi", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + dataTableName + " WHERE API_KEY = '" + APIKey + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (hasStuff && res.getString("API_KEY") != null) {
+ UserAPIAccount account = new UserAPIAccount();
+ account.setAPIKey(APIKey);
+ account.setUserId(res.getString("USER_ID"));
+ account.setBlocked(res.getBoolean("BLOCKED"));
+ account.setTimeIssued(res.getLong("TIME_ISSUED"));
+ account.setUses(res.getInt("USES"));
+
+ statement.close();
+
+ return account;
+ } else {
+ //Data not present.
+ statement.close();
+ return null;
+ }
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get API Account.", e, this.getClass(), true);
+ }
+ return null;
+ }
+
+ public GuildSettings getSettings(long guildId) {
+ GuildSettings settings = new GuildSettings(guildId);
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String dataTableName = String.format("%sguild_settings", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + dataTableName + " WHERE GUILD_ID = '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (hasStuff && res.getString("GUILD_ID") != null) {
+ settings.setUseExternalCalendar(res.getBoolean("EXTERNAL_CALENDAR"));
+ settings.setPrivateKey(res.getString("PRIVATE_KEY"));
+ settings.setEncryptedAccessToken(res.getString("ACCESS_TOKEN"));
+ settings.setEncryptedRefreshToken(res.getString("REFRESH_TOKEN"));
+ settings.setControlRole(res.getString("CONTROL_ROLE"));
+ settings.setDiscalChannel(res.getString("DISCAL_CHANNEL"));
+ settings.setSimpleAnnouncements(res.getBoolean("SIMPLE_ANNOUNCEMENT"));
+ settings.setLang(res.getString("LANG"));
+ settings.setPrefix(res.getString("PREFIX"));
+ settings.setPatronGuild(res.getBoolean("PATRON_GUILD"));
+ settings.setDevGuild(res.getBoolean("DEV_GUILD"));
+ settings.setMaxCalendars(res.getInt("MAX_CALENDARS"));
+ settings.setDmAnnouncementsFromString(res.getString("DM_ANNOUNCEMENTS"));
+ settings.setTwelveHour(res.getBoolean("12_HOUR"));
+ settings.setBranded(res.getBoolean("BRANDED"));
+
+ statement.close();
+ } else {
+ //Data not present.
+ statement.close();
+ return settings;
+ }
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get Guild Settings.", e, this.getClass(), true);
+ }
+ return settings;
+ }
+
+ public ArrayList getAllSettings() {
+ ArrayList allSettings = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String dataTableName = String.format("%sguild_settings", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + dataTableName);
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("GUILD_ID") != null) {
+ GuildSettings settings = new GuildSettings(Long.valueOf(res.getString("GUILD_ID")));
+ settings.setUseExternalCalendar(res.getBoolean("EXTERNAL_CALENDAR"));
+ settings.setPrivateKey(res.getString("PRIVATE_KEY"));
+ settings.setEncryptedAccessToken(res.getString("ACCESS_TOKEN"));
+ settings.setEncryptedRefreshToken(res.getString("REFRESH_TOKEN"));
+ settings.setControlRole(res.getString("CONTROL_ROLE"));
+ settings.setDiscalChannel(res.getString("DISCAL_CHANNEL"));
+ settings.setSimpleAnnouncements(res.getBoolean("SIMPLE_ANNOUNCEMENT"));
+ settings.setLang(res.getString("LANG"));
+ settings.setPrefix(res.getString("PREFIX"));
+ settings.setPatronGuild(res.getBoolean("PATRON_GUILD"));
+ settings.setDevGuild(res.getBoolean("DEV_GUILD"));
+ settings.setMaxCalendars(res.getInt("MAX_CALENDARS"));
+ settings.setDmAnnouncementsFromString(res.getString("DM_ANNOUNCEMENTS"));
+ settings.setBranded(res.getBoolean("BRANDED"));
+
+ allSettings.add(settings);
+ }
+ }
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all guild settings", e, this.getClass(), true);
+ }
+ return allSettings;
+ }
+
+ public CalendarData getMainCalendar(long guildId) {
+ CalendarData calData = new CalendarData(guildId, 1);
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ if (res.getInt("CALENDAR_NUMBER") == 1) {
+ calData.setCalendarId(res.getString("CALENDAR_ID"));
+ calData.setCalendarAddress(res.getString("CALENDAR_ADDRESS"));
+ calData.setExternal(res.getBoolean("EXTERNAL"));
+ break;
+ }
+ }
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get calendar settings.", e, this.getClass(), true);
+ }
+ return calData;
+ }
+
+ public CalendarData getCalendar(long guildId, int calendarNumber) {
+ CalendarData calData = new CalendarData(guildId, calendarNumber);
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ if (res.getInt("CALENDAR_NUMBER") == calendarNumber) {
+ calData.setCalendarId(res.getString("CALENDAR_ID"));
+ calData.setCalendarAddress(res.getString("CALENDAR_ADDRESS"));
+ calData.setExternal(res.getBoolean("EXTERNAL"));
+ break;
+ }
+ }
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get calendar data", e, this.getClass(), true);
+ }
+ return calData;
+ }
+
+ public ArrayList getAllCalendars(long guildId) {
+ ArrayList calendars = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ CalendarData calData = new CalendarData(guildId, res.getInt("CALENDAR_NUMBER"));
+ calData.setCalendarId(res.getString("CALENDAR_ID"));
+ calData.setCalendarAddress(res.getString("CALENDAR_ADDRESS"));
+ calData.setExternal(res.getBoolean("EXTERNAL"));
+ calendars.add(calData);
+ }
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all guild calendars.", e, this.getClass(), true);
+ }
+ return calendars;
+ }
+
+ public ArrayList getAllCalendars() {
+ ArrayList calendars = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + calendarTableName);
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ CalendarData calData = new CalendarData(Long.valueOf(res.getString("GUILD_ID")), res.getInt("CALENDAR_NUMBER"));
+ calData.setCalendarId(res.getString("CALENDAR_ID"));
+ calData.setCalendarAddress(res.getString("CALENDAR_ADDRESS"));
+ calData.setExternal(res.getBoolean("EXTERNAL"));
+ calendars.add(calData);
+ }
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all calendars!", e, this.getClass(), true);
+ }
+ return calendars;
+ }
+
+ public int getCalendarCount() {
+ int amount = -1;
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTableName = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "SELECT COUNT(*) FROM " + calendarTableName + ";";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ if (res.next())
+ amount = res.getInt(1);
+ else
+ amount = 0;
+
+
+ res.close();
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get calendar count", e, this.getClass(), true);
+ }
+ return amount;
+ }
+
+ public EventData getEventData(long guildId, String eventId) {
+ EventData data = new EventData(guildId);
+
+ if (eventId.contains("_"))
+ eventId = eventId.split("_")[0];
+
+
+ data.setEventId(eventId);
+
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String eventTableName = String.format("%sevents", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + eventTableName + " WHERE GUILD_ID= '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("EVENT_ID").equals(eventId)) {
+ data.setEventEnd(res.getLong("EVENT_END"));
+ data.setImageLink(res.getString("IMAGE_LINK"));
+ break;
+ }
+ }
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get event data", e, this.getClass(), true);
+ }
+ return data;
+ }
+
+ public ArrayList getAllEventData() {
+ ArrayList allData = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String eventTableName = String.format("%sevents", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + eventTableName);
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("EVENT_ID") != null) {
+ EventData data = new EventData(Long.valueOf(res.getString("GUILD_ID")));
+
+ data.setEventId(res.getString("EVENT_ID"));
+ data.setEventEnd(res.getLong("EVENT_END"));
+ data.setImageLink(res.getString("IMAGE_LINK"));
+
+ allData.add(data);
+ }
+ }
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all event data", e, this.getClass(), true);
+ }
+ return allData;
+ }
+
+ public RsvpData getRsvpData(long guildId, String eventId) {
+ RsvpData data = new RsvpData(guildId);
+ data.setEventId(eventId);
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String rsvpTableName = String.format("%srsvp", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + rsvpTableName + " WHERE GUILD_ID= '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("EVENT_ID").equals(eventId)) {
+ data.setEventEnd(res.getLong("EVENT_END"));
+ data.setGoingOnTimeFromString(res.getString("GOING_ON_TIME"));
+ data.setGoingLateFromString(res.getString("GOING_LATE"));
+ data.setNotGoingFromString(res.getString("NOT_GOING"));
+ data.setUndecidedFromString(res.getString("UNDECIDED"));
+ break;
+ }
+ }
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get RSVP data for event", e, this.getClass(), true);
+ }
+ return data;
+ }
+
+ public ArrayList getAllRsvpData() {
+ ArrayList dataList = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String rsvpTableName = String.format("%srsvp", databaseInfo.getPrefix());
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + rsvpTableName);
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("GUILD_ID") != null) {
+ RsvpData data = new RsvpData(Long.valueOf(res.getString("GUILD_ID")));
+ data.setEventId(res.getString("EVENT_ID"));
+ data.setEventEnd(res.getLong("EVENT_END"));
+ data.setGoingOnTimeFromString(res.getString("GOING_ON_TIME"));
+ data.setGoingLateFromString(res.getString("GOING_LATE"));
+ data.setNotGoingFromString(res.getString("NOT_GOING"));
+ data.setUndecidedFromString(res.getString("UNDECIDED"));
+
+ dataList.add(data);
+ }
+ }
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all RSVP Data!", e, this.getClass(), true);
+ }
+ return dataList;
+ }
+
+ /**
+ * Gets the {@link Announcement} Object with the corresponding ID for the specified Guild.
+ *
+ * @param announcementId The ID of the announcement.
+ * @param guildId The ID of the guild the Announcement belongs to.
+ * @return The {@link Announcement} with the specified ID if it exists, otherwise null.
+ */
+ public Announcement getAnnouncement(UUID announcementId, long guildId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = '" + announcementId.toString() + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ boolean hasStuff = res.next();
+
+ if (hasStuff && res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(announcementId, guildId);
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(AnnouncementType.valueOf(res.getString("ANNOUNCEMENT_TYPE")));
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setEnabled(res.getBoolean("ENABLED"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ statement.close();
+ return announcement;
+ }
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get announcement data.", e, this.getClass(), true);
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Gets an {@link ArrayList} of {@link Announcement}s belonging to the specific Guild.
+ *
+ * @param guildId The ID of the guild whose data is to be retrieved.
+ * @return An ArrayList of Announcements that belong to the specified Guild.
+ */
+ public ArrayList getAnnouncements(long guildId) {
+ ArrayList announcements = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "SELECT * FROM " + announcementTableName + " WHERE GUILD_ID = '" + String.valueOf(guildId) + "';";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(UUID.fromString(res.getString("ANNOUNCEMENT_ID")), guildId);
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(AnnouncementType.valueOf(res.getString("ANNOUNCEMENT_TYPE")));
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setEnabled(res.getBoolean("ENABLED"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ announcements.add(announcement);
+ }
+ }
+
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all guild announcements.", e, this.getClass(), true);
+ e.printStackTrace();
+ }
+ return announcements;
+ }
+
+ public ArrayList getAnnouncements() {
+ ArrayList announcements = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + announcementTableName);
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(UUID.fromString(res.getString("ANNOUNCEMENT_ID")), Long.valueOf(res.getString("GUILD_ID")));
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(AnnouncementType.valueOf(res.getString("ANNOUNCEMENT_TYPE")));
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setEnabled(res.getBoolean("ENABLED"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ announcements.add(announcement);
+ }
+ }
+
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all announcements.", e, this.getClass(), true);
+ }
+
+ return announcements;
+ }
+
+ public ArrayList getAnnouncements(AnnouncementType type) {
+ ArrayList announcements = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + announcementTableName + " WHERE ANNOUNCEMENT_TYPE = ?");
+ stmt.setString(1, type.name());
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(UUID.fromString(res.getString("ANNOUNCEMENT_ID")), Long.valueOf(res.getString("GUILD_ID")));
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(type);
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setEnabled(res.getBoolean("ENABLED"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ announcements.add(announcement);
+ }
+ }
+
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all announcements by type.", e, this.getClass(), true);
+ }
+
+ return announcements;
+ }
+
+ public ArrayList getEnabledAnnouncements() {
+ ArrayList announcements = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + announcementTableName + " WHERE ENABLED = 1");
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(UUID.fromString(res.getString("ANNOUNCEMENT_ID")), Long.valueOf(res.getString("GUILD_ID")));
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(AnnouncementType.valueOf(res.getString("ANNOUNCEMENT_TYPE")));
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ //The announcement is obviously enabled if we have gotten here lol
+ announcement.setEnabled(true);
+
+ announcements.add(announcement);
+ }
+ }
+
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all enabled announcements.", e, this.getClass(), true);
+ }
+
+ return announcements;
+ }
+
+ public ArrayList getEnabledAnnouncements(AnnouncementType type) {
+ ArrayList announcements = new ArrayList<>();
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ PreparedStatement stmt = databaseInfo.getConnection().prepareStatement("SELECT * FROM " + announcementTableName + " WHERE ENABLED = 1 AND ANNOUNCEMENT_TYPE = ?");
+ stmt.setString(1, type.name());
+ ResultSet res = stmt.executeQuery();
+
+ while (res.next()) {
+ if (res.getString("ANNOUNCEMENT_ID") != null) {
+ Announcement announcement = new Announcement(UUID.fromString(res.getString("ANNOUNCEMENT_ID")), Long.valueOf(res.getString("GUILD_ID")));
+ announcement.setSubscriberRoleIdsFromString(res.getString("SUBSCRIBERS_ROLE"));
+ announcement.setSubscriberUserIdsFromString(res.getString("SUBSCRIBERS_USER"));
+ announcement.setAnnouncementChannelId(res.getString("CHANNEL_ID"));
+ announcement.setAnnouncementType(type);
+ announcement.setEventId(res.getString("EVENT_ID"));
+ announcement.setEventColor(EventColor.fromNameOrHexOrID(res.getString("EVENT_COLOR")));
+ announcement.setHoursBefore(res.getInt("HOURS_BEFORE"));
+ announcement.setMinutesBefore(res.getInt("MINUTES_BEFORE"));
+ announcement.setInfo(res.getString("INFO"));
+ announcement.setInfoOnly(res.getBoolean("INFO_ONLY"));
+
+ //The announcement is obviously enabled if we have gotten here lol
+ announcement.setEnabled(true);
+
+ announcements.add(announcement);
+ }
+ }
+
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get all enabled announcements by type.", e, this.getClass(), true);
+ }
+
+ return announcements;
+ }
+
+ public int getAnnouncementCount() {
+ int amount = -1;
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "SELECT COUNT(*) FROM " + announcementTableName + ";";
+ PreparedStatement statement = databaseInfo.getConnection().prepareStatement(query);
+ ResultSet res = statement.executeQuery();
+
+ if (res.next())
+ amount = res.getInt(1);
+ else
+ amount = 0;
+
+ res.close();
+ statement.close();
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to get announcement count", e, this.getClass(), true);
+ }
+ return amount;
+ }
+
+ /**
+ * Deletes the specified announcement from the Database.
+ *
+ * @param announcementId The ID of the announcement to delete.
+ * @return true if successful, else false.
+ */
+ public boolean deleteAnnouncement(String announcementId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, announcementId);
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete announcement.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteAnnouncementsForEvent(long guildId, String eventId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTableName = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + announcementTableName + " WHERE EVENT_ID = ? AND GUILD_ID = ? AND ANNOUNCEMENT_TYPE = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, eventId);
+ preparedStmt.setString(2, String.valueOf(guildId));
+ preparedStmt.setString(3, AnnouncementType.SPECIFIC.name());
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete announcements for specific event.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteEventData(String eventId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String eventTable = String.format("%sevents", databaseInfo.getPrefix());
+
+ //Check if recurring...
+ if (eventId.contains("_"))
+ return false; //Don't delete if child event of recurring event.
+
+
+ String query = "DELETE FROM " + eventTable + " WHERE EVENT_ID = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, eventId);
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete event data.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteAllEventData(long guildId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String eventTable = String.format("%sevents", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + eventTable + " WHERE GUILD_ID = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, String.valueOf(guildId));
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete all event data for guild.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteAllAnnouncementData(long guildId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String announcementTable = String.format("%sannouncements", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + announcementTable + " WHERE GUILD_ID = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, String.valueOf(guildId));
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete all announcements for guild.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteAllRSVPData(long guildId) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String rsvpTable = String.format("%srsvp", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + rsvpTable + " WHERE GUILD_ID = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, String.valueOf(guildId));
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete all RSVP data for guild.", e, this.getClass(), true);
+ }
+ return false;
+ }
+
+ public boolean deleteCalendar(CalendarData data) {
+ try {
+ if (databaseInfo.getMySQL().checkConnection()) {
+ String calendarTable = String.format("%scalendars", databaseInfo.getPrefix());
+
+ String query = "DELETE FROM " + calendarTable + " WHERE GUILD_ID = ? AND CALENDAR_ADDRESS = ?";
+ PreparedStatement preparedStmt = databaseInfo.getConnection().prepareStatement(query);
+ preparedStmt.setString(1, String.valueOf(data.getGuildId()));
+ preparedStmt.setString(2, data.getCalendarAddress());
+
+ preparedStmt.execute();
+ preparedStmt.close();
+ return true;
+ }
+ } catch (SQLException e) {
+ Logger.getLogger().exception(null, "Failed to delete calendar from database for guild.", e, this.getClass(), true);
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/database/MySQL.java b/src/main/java/com/cloudcraftgaming/discal/api/database/MySQL.java
new file mode 100644
index 00000000..fe02d6ef
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/database/MySQL.java
@@ -0,0 +1,69 @@
+package com.cloudcraftgaming.discal.api.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+public class MySQL extends Database {
+ private final String user;
+ private final String database;
+ private final String password;
+ private final String port;
+ private final String hostname;
+ private final String prefix;
+
+ /**
+ * Creates a new MySQL instance
+ *
+ * @param hostname Name of the host
+ * @param port Port number
+ * @param username Username
+ * @param password Password
+ */
+ public MySQL(String hostname, String port, String prefix, String username, String password) {
+ this(hostname, port, null, prefix, username, password);
+ }
+
+ /**
+ * Creates a new MySQL instance for a specific database
+ *
+ * @param hostname Name of the host
+ * @param port Port number
+ * @param database Database name
+ * @param username Username
+ * @param password Password
+ */
+ public MySQL(String hostname, String port, String database, String prefix, String username, String password) {
+ this.hostname = hostname;
+ this.port = port;
+ this.database = database;
+ this.user = username;
+ this.password = password;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public Connection openConnection() throws SQLException, ClassNotFoundException {
+ if (checkConnection())
+ return connection;
+
+ String connectionURL = "jdbc:mysql://" + this.hostname + ":" + this.port;
+ if (database != null)
+ connectionURL = connectionURL + "/" + this.database + "?autoReconnect=true&useSSL=false";
+
+
+ Class.forName("com.mysql.jdbc.Driver");
+ connection = DriverManager.getConnection(connectionURL, this.user, this.password);
+ return connection;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/database/SQLite.java b/src/main/java/com/cloudcraftgaming/discal/api/database/SQLite.java
new file mode 100644
index 00000000..c2538217
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/database/SQLite.java
@@ -0,0 +1,50 @@
+package com.cloudcraftgaming.discal.api.database;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings({"unused", "ResultOfMethodCallIgnored"})
+public class SQLite extends Database {
+ private final String dbLocation;
+
+ /**
+ * Creates a new SQLite instance
+ *
+ * @param dbLocation Location of the Database (Must end in .db)
+ */
+ public SQLite(String dbLocation) {
+ this.dbLocation = dbLocation;
+ }
+
+ @Override
+ public Connection openConnection() throws SQLException, ClassNotFoundException {
+ if (checkConnection())
+ return connection;
+
+
+ File dataFolder = new File("sqlite-db/");
+ if (!dataFolder.exists())
+ dataFolder.mkdirs();
+
+
+ File file = new File(dataFolder, dbLocation);
+ if (!(file.exists())) {
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ System.out.println("Unable to create database!");
+ }
+ }
+ Class.forName("org.sqlite.JDBC");
+ connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder + "/" + dbLocation);
+ return connection;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/enums/BadTimezone.java b/src/main/java/com/cloudcraftgaming/discal/api/enums/BadTimezone.java
new file mode 100644
index 00000000..bc6276ee
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/enums/BadTimezone.java
@@ -0,0 +1,11 @@
+package com.cloudcraftgaming.discal.api.enums;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings("unused")
+public enum BadTimezone {
+ America_Adak, America_Atka, US_Aleutian, HST, America_Juneau, America_Nome, America_Yakutat, America_Dawson, PST8PDT, America_Boise, America_Cambridge_Bay, America_Chihuahua, America_Inuvik, America_Ojinaga, MST, MST7MDT, America_Bahia_Banderas, America_Indiana_Knox, America_Indiana_Tell_City, America_Matamoros, America_Menominee, America_Merida, America_Monterrey, America_North_Dakota_Center, America_North_Dakota_New_Salem, America_Rainy_River, America_Rankin_Inlet, America_Swift_Current, America_Atikokan, America_Coral_Harbour, US_Michigan, America_Indiana_Indianapolis, America_Indiana_Marengo, America_Indiana_Petersburg, America_Indiana_Vevay, America_Indiana_Vincennes, America_Indiana_Winamac, America_Kentucky_Louisville, America_Louisville, America_Kentucky_Monticello, America_Nipigon, America_Pangnirtung, America_Resolute, America_Thunder_Bay, EST, EST5EDT, America_Argentina_San_Luis, America_Eirunepe, America_Glace_Bay, America_Goose_Bay, America_Moncton, America_Argentina_Catamarca, America_Argentina_ComodRivadavia, America_Catamarca, America_Argentina_Cordoba, America_Cordoba, America_Rosario, America_Argentina_Jujuy, America_Jujuy, America_Argentina_La_Rioja, America_Argentina_Mendoza, America_Mendoza, America_Argentina_Rio_Gallegos, America_Argentina_Salta, America_Argentina_San_Juan, America_Argentina_Tucuman, America_Argentina_Ushuaia, America_Santarem, Atlantic_Madeira, Etc_UCT, UCT, Etc_UTC, Etc_Universal, Etc_Zulu, Universal, Zulu, CET, MET, EET, Europe_Simferopol, Europe_Uzhgorod, Europe_Zaporozhye, Europe_Volgograd, Asia_Oral, Asia_Samarkand, Asia_Novokuznetsk, Asia_Pontianak, Asia_Kashgar, Asia_Kuching, Asia_Urumqi, Asia_Sakhalin, Antarctica_Macquarie, Asia_Anadyr, Pacific_Chatham, America_Detroit
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/enums/GoodTimezone.java b/src/main/java/com/cloudcraftgaming/discal/api/enums/GoodTimezone.java
new file mode 100644
index 00000000..17f8f558
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/enums/GoodTimezone.java
@@ -0,0 +1,10 @@
+package com.cloudcraftgaming.discal.api.enums;
+
+/**
+ * Created by Nova Fox on 1___7___18.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+public enum GoodTimezone {
+ Africa___Abidjan, Africa___Accra, Africa___Addis_Ababa, Africa___Algiers, Africa___Asmara, Africa___Asmera, Africa___Bamako, Africa___Bangui, Africa___Banjul, Africa___Bissau, Africa___Blantyre, Africa___Brazzaville, Africa___Bujumbura, Africa___Cairo, Africa___Casablanca, Africa___Ceuta, Africa___Conakry, Africa___Dakar, Africa___Dar_es_Salaam, Africa___Djibouti, Africa___Douala, Africa___El_Aaiun, Africa___Freetown, Africa___Gaborone, Africa___Harare, Africa___Johannesburg, Africa___Kampala, Africa___Khartoum, Africa___Kigali, Africa___Kinshasa, Africa___Lagos, Africa___Libreville, Africa___Lome, Africa___Luanda, Africa___Lubumbashi, Africa___Lusaka, Africa___Malabo, Africa___Maputo, Africa___Maseru, Africa___Mbabane, Africa___Monrovia, Africa___Ndjamena, Africa___Niamey, Africa___Nouakchott, Africa___Ouagadougou, Africa___Sao_Tome, Africa___Timbuktu, Africa___Tunis, Africa___Windhoek, America___Anchorage, America___Anguilla, America___Antigua, America___Araguaina, America___Argentina___Buenos_Aires, America___Aruba, America___Asuncion, America___Bahia, America___Barbados, America___Belem, America___Belize, America___Boa_Vista, America___Bogota, America___Buenos_Aires, America___Campo_Grande, America___Cancun, America___Caracas, America___Cayenne, America___Cayman, America___Chicago, America___Costa_Rica, America___Cuiaba, America___Curacao, America___Danmarkshavn, America___Dawson_Creek, America___Denver, America___Dominica, America___Edmonton, America___El_Salvador, America___Ensenada, America___Fortaleza, America___Godthab, America___Grand_Turk, America___Grenada, America___Guadeloupe, America___Guatemala, America___Guayaquil, America___Guyana, America___Halifax, America___Havana, America___Hermosillo, America___Iqaluit, America___Jamaica, America___La_Paz, America___Lima, America___Los_Angeles, America___Maceio, America___Managua, America___Manaus, America___Marigot, America___Martinique, America___Mazatlan, America___Mexico_City, America___Miquelon, America___Montevideo, America___Montserrat, America___Nassau, America___New_York, America___Noronha, America___Panama, America___Paramaribo, America___Phoenix, America___Port_of_Spain, America___Porto_Acre, America___Porto_Velho, America___Puerto_Rico, America___Recife, America___Regina, America___Rio_Branco, America___Santa_Isabel, America___Santiago, America___Santo_Domingo, America___Sao_Paulo, America___Scoresbysund, America___Shiprock, America___St_Barthelemy, America___St_Johns, America___St_Kitts, America___St_Lucia, America___St_Thomas, America___St_Vincent, America___Tegucigalpa, America___Thule, America___Tijuana, America___Toronto, America___Tortola, America___Vancouver, America___Virgin, America___Whitehorse, America___Winnipeg, America___Yellowknife, Antarctica___Casey, Antarctica___Davis, Antarctica___DumontDUrville, Antarctica___Mawson, Antarctica___McMurdo, Antarctica___Palmer, Antarctica___Rothera, Antarctica___South_Pole, Antarctica___Syowa, Antarctica___Vostok, Arctic___Longyearbyen, Asia___Aden, Asia___Almaty, Asia___Amman, Asia___Aqtau, Asia___Aqtobe, Asia___Ashgabat, Asia___Ashkhabad, Asia___Baghdad, Asia___Bahrain, Asia___Baku, Asia___Bangkok, Asia___Beirut, Asia___Bishkek, Asia___Brunei, Asia___Calcutta, Asia___Chongqing, Asia___Chungking, Asia___Colombo, Asia___Dacca, Asia___Damascus, Asia___Dhaka, Asia___Dili, Asia___Dubai, Asia___Dushanbe, Asia___Gaza, Asia___Harbin, Asia___Ho_Chi_Minh, Asia___Hong_Kong, Asia___Hovd, Asia___Irkutsk, Asia___Istanbul, Asia___Jakarta, Asia___Jayapura, Asia___Jerusalem, Asia___Kabul, Asia___Kamchatka, Asia___Karachi, Asia___Kathmandu, Asia___Katmandu, Asia___Kolkata, Asia___Krasnoyarsk, Asia___Kuala_Lumpur, Asia___Kuwait, Asia___Macao, Asia___Macau, Asia___Magadan, Asia___Makassar, Asia___Manila, Asia___Muscat, Asia___Nicosia, Asia___Novosibirsk, Asia___Omsk, Asia___Phnom_Penh, Asia___Pyongyang, Asia___Qatar, Asia___Qyzylorda, Asia___Rangoon, Asia___Riyadh, Asia___Saigon, Asia___Seoul, Asia___Shanghai, Asia___Singapore, Asia___Taipei, Asia___Tashkent, Asia___Tbilisi, Asia___Tehran, Asia___Tel_Aviv, Asia___Thimbu, Asia___Thimphu, Asia___Tokyo, Asia___Ujung_Pandang, Asia___Ulaanbaatar, Asia___Ulan_Bator, Asia___Vientiane, Asia___Vladivostok, Asia___Yakutsk, Asia___Yekaterinburg, Asia___Yerevan, Atlantic___Azores, Atlantic___Bermuda, Atlantic___Canary, Atlantic___Cape_Verde, Atlantic___Faeroe, Atlantic___Faroe, Atlantic___Jan_Mayen, Atlantic___Reykjavik, Atlantic___South_Georgia, Atlantic___St_Helena, Atlantic___Stanley, Brazil___Acre, Brazil___DeNoronha, Brazil___East, Brazil___West, CST6CDT, Canada___Atlantic, Canada___Eastern, Canada___Mountain, Canada___Newfoundland, Canada___Pacific, Canada___Yukon, Chile___Continental, Chile___EasterIsland, Cuba, Egypt, Eire, Etc___GMT, Europe___Amsterdam, Europe___Andorra, Europe___Athens, Europe___Belgrade, Europe___Berlin, Europe___Bratislava, Europe___Brussels, Europe___Bucharest, Europe___Budapest, Europe___Chisinau, Europe___Copenhagen, Europe___Dublin, Europe___Gibraltar, Europe___Helsinki, Europe___Istanbul, Europe___Kaliningrad, Europe___Kiev, Europe___Lisbon, Europe___Ljubljana, Europe___London, Europe___Luxembourg, Europe___Madrid, Europe___Malta, Europe___Mariehamn, Europe___Minsk, Europe___Monaco, Europe___Moscow, Europe___Nicosia, Europe___Oslo, Europe___Paris, Europe___Podgorica, Europe___Prague, Europe___Riga, Europe___Rome, Europe___Samara, Europe___San_Marino, Europe___Sarajevo, Europe___Skopje, Europe___Sofia, Europe___Stockholm, Europe___Tallinn, Europe___Tirane, Europe___Tiraspol, Europe___Vaduz, Europe___Vatican, Europe___Vienna, Europe___Vilnius, Europe___Warsaw, Europe___Zagreb, Europe___Zurich, Hongkong, Iceland, Indian___Antananarivo, Indian___Chagos, Indian___Christmas, Indian___Cocos, Indian___Comoro, Indian___Kerguelen, Indian___Mahe, Indian___Maldives, Indian___Mauritius, Indian___Mayotte, Indian___Reunion, Iran, Israel, Jamaica, Japan, Kwajalein, Libya, Mexico___BajaNorte, Mexico___BajaSur, Mexico___General, NZ, Navajo, PRC, Pacific___Apia, Pacific___Auckland, Pacific___Chuuk, Pacific___Easter, Pacific___Efate, Pacific___Enderbury, Pacific___Fakaofo, Pacific___Fiji, Pacific___Funafuti, Pacific___Galapagos, Pacific___Gambier, Pacific___Guadalcanal, Pacific___Guam, Pacific___Honolulu, Pacific___Johnston, Pacific___Kiritimati, Pacific___Kosrae, Pacific___Kwajalein, Pacific___Majuro, Pacific___Marquesas, Pacific___Midway, Pacific___Nauru, Pacific___Niue, Pacific___Norfolk, Pacific___Noumea, Pacific___Pago_Pago, Pacific___Palau, Pacific___Pitcairn, Pacific___Pohnpei, Pacific___Ponape, Pacific___Port_Moresby, Pacific___Rarotonga, Pacific___Saipan, Pacific___Samoa, Pacific___Tahiti, Pacific___Tarawa, Pacific___Tongatapu, Pacific___Wake, Pacific___Wallis, Poland, Portugal, ROC, ROK, Singapore, Turkey, UCT, US___Alaska, US___Arizona, US___Eastern, US___Hawaii, US___Mountain, US___Samoa, UTC, Universal, Zulu
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/enums/announcement/AnnouncementType.java b/src/main/java/com/cloudcraftgaming/discal/api/enums/announcement/AnnouncementType.java
new file mode 100644
index 00000000..831355d6
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/enums/announcement/AnnouncementType.java
@@ -0,0 +1,43 @@
+package com.cloudcraftgaming.discal.api.enums.announcement;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+public enum AnnouncementType {
+ UNIVERSAL, SPECIFIC, COLOR, RECUR;
+
+ /**
+ * Checks if the specified value is a valid AnnouncementType.
+ *
+ * @param _value The value to check.
+ * @return true if value, otherwise false.
+ */
+ public static Boolean isValid(String _value) {
+ return _value.equalsIgnoreCase("UNIVERSAL") || _value.equalsIgnoreCase("SPECIFIC") || _value.equalsIgnoreCase("COLOR") || _value.equalsIgnoreCase("COLOUR") || _value.equalsIgnoreCase("RECUR");
+ }
+
+ /**
+ * Gets the AnnouncementType from the value.
+ *
+ * @param _value The value to check.
+ * @return The AnnouncementType.
+ */
+ public static AnnouncementType fromValue(String _value) {
+ switch (_value.toUpperCase()) {
+ case "UNIVERSAL":
+ return UNIVERSAL;
+ case "SPECIFIC":
+ return SPECIFIC;
+ case "COLOR":
+ return COLOR;
+ case "COLOUR":
+ return COLOR;
+ case "RECUR":
+ return RECUR;
+ default:
+ return UNIVERSAL;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventColor.java b/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventColor.java
new file mode 100644
index 00000000..091340c4
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventColor.java
@@ -0,0 +1,104 @@
+package com.cloudcraftgaming.discal.api.enums.event;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+@SuppressWarnings("SpellCheckingInspection")
+public enum EventColor {
+ MELROSE(1, "A4BDFC", 164, 189, 252), RIPTIDE(2, "7AE7BF", 122, 231, 191),
+ MAUVE(3, "DBADFF", 219, 173, 255), TANGERINE(4, "FF887C", 255, 136, 124),
+ DANDELION(5, "FBD75B", 251, 215, 91), MAC_AND_CHEESE(6, "FFB878", 255, 184, 120),
+ TURQUOISE(7, "46D6DB", 70, 214, 219), MERCURY(8, "E1E1E1", 255, 255, 255),
+ BLUE(9, "5484ED", 84, 132, 237), GREEN(10, "51B749", 81, 183, 73),
+ RED(11, "DC2127", 220, 33, 39), NONE(12, "NONE", 56, 138, 237);
+
+ private final Integer id;
+ private final String hex;
+
+ private final Integer r;
+ private final Integer g;
+ private final Integer b;
+
+ EventColor(Integer _id, String _hex, Integer _r, Integer _g, Integer _b) {
+ id = _id;
+ hex = _hex;
+
+ r = _r;
+ b = _b;
+ g = _g;
+ }
+
+
+ public int getId() {
+ return id;
+ }
+
+ public String getHex() {
+ return hex;
+ }
+
+ public int getR() {
+ return r;
+ }
+
+ public int getG() {
+ return g;
+ }
+
+ public int getB() {
+ return b;
+ }
+
+ //Static methods
+ public static boolean exists(String nameOrHexOrId) {
+ for (EventColor c: values()) {
+ if (c.name().equalsIgnoreCase(nameOrHexOrId) || c.getHex().equals(nameOrHexOrId)) {
+ return true;
+ } else {
+ try {
+ int i = Integer.valueOf(nameOrHexOrId);
+ if (c.getId() == i)
+ return true;
+ } catch (NumberFormatException e) {
+ //Not number, just ignore.
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean exists(Integer id) {
+ for (EventColor c: values()) {
+ if (c.getId() == id)
+ return true;
+ }
+ return false;
+ }
+
+ public static EventColor fromNameOrHexOrID(String nameOrHexOrID) {
+ for (EventColor c: values()) {
+ if (c.name().equalsIgnoreCase(nameOrHexOrID) || c.getHex().equals(nameOrHexOrID)) {
+ return c;
+ } else {
+ try {
+ int i = Integer.valueOf(nameOrHexOrID);
+ if (c.getId() == i)
+ return c;
+ } catch (NumberFormatException e) {
+ //Not number, just ignore.
+ }
+ }
+ }
+ return NONE;
+ }
+
+ public static EventColor fromId(Integer id) {
+ for (EventColor c: values()) {
+ if (c.getId() == id)
+ return c;
+ }
+ return NONE;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventFrequency.java b/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventFrequency.java
new file mode 100644
index 00000000..fec54288
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/enums/event/EventFrequency.java
@@ -0,0 +1,41 @@
+package com.cloudcraftgaming.discal.api.enums.event;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+public enum EventFrequency {
+ HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY;
+
+ /**
+ * Checks if the value is a valid enum value.
+ *
+ * @param value The value to check.
+ * @return true if valid, else false.
+ */
+ public static boolean isValid(String value) {
+ return value.equalsIgnoreCase("DAILY") || value.equalsIgnoreCase("WEEKLY") || value.equalsIgnoreCase("MONTHLY") || value.equalsIgnoreCase("YEARLY");
+ }
+
+ /**
+ * Gets the enum value for the specified string value.
+ *
+ * @param value The value to get from.
+ * @return The enum value.
+ */
+ public static EventFrequency fromValue(String value) {
+ switch (value.toUpperCase()) {
+ case "DAILY":
+ return DAILY;
+ case "WEEKLY":
+ return WEEKLY;
+ case "MONTHLY":
+ return MONTHLY;
+ case "YEARLY":
+ return YEARLY;
+ default:
+ return DAILY;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cloudcraftgaming/discal/api/file/ReadFile.java b/src/main/java/com/cloudcraftgaming/discal/api/file/ReadFile.java
new file mode 100644
index 00000000..66adeece
--- /dev/null
+++ b/src/main/java/com/cloudcraftgaming/discal/api/file/ReadFile.java
@@ -0,0 +1,44 @@
+package com.cloudcraftgaming.discal.api.file;
+
+import com.cloudcraftgaming.discal.api.object.BotSettings;
+import com.cloudcraftgaming.discal.logger.Logger;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import java.io.File;
+import java.io.FileReader;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by Nova Fox on 11/10/17.
+ * Website: www.cloudcraftgaming.com
+ * For Project: DisCal-Discord-Bot
+ */
+public class ReadFile {
+ @SuppressWarnings({"unchecked", "ConstantConditions"})
+ public static Map> readAllLangFiles() {
+ Map> langs = new HashMap<>();
+
+ try {
+ File langDir = new File(BotSettings.LANG_PATH.get());
+
+ for (File f: langDir.listFiles()) {
+ // Open the file
+ FileReader fr = new FileReader(f);
+
+ Type type = new TypeToken