package org.dreamexposure.discal.core.database; import discord4j.core.object.util.Snowflake; import org.dreamexposure.discal.core.crypto.KeyGenerator; import org.dreamexposure.discal.core.enums.announcement.AnnouncementType; import org.dreamexposure.discal.core.enums.event.EventColor; import org.dreamexposure.discal.core.logger.Logger; import org.dreamexposure.discal.core.object.BotSettings; import org.dreamexposure.discal.core.object.GuildSettings; import org.dreamexposure.discal.core.object.announcement.Announcement; import org.dreamexposure.discal.core.object.calendar.CalendarData; import org.dreamexposure.discal.core.object.event.EventData; import org.dreamexposure.discal.core.object.event.RsvpData; import org.dreamexposure.discal.core.object.web.UserAPIAccount; import org.dreamexposure.novautils.database.DatabaseInfo; import org.dreamexposure.novautils.database.DatabaseSettings; import org.flywaydb.core.Flyway; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * Created by Nova Fox on 11/10/17. * Website: www.cloudcraftgaming.com * For Project: DisCal-Discord-Bot */ @SuppressWarnings({"UnusedReturnValue", "SqlNoDataSourceInspection", "Duplicates", "SqlResolve", "unused"}) public class DatabaseManager { private static DatabaseManager instance; private DatabaseInfo masterInfo; private DatabaseInfo slaveInfo; private Map<Snowflake, GuildSettings> guildSettingsCache = new HashMap<>(); 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 { DatabaseSettings masterSettings = new DatabaseSettings(BotSettings.SQL_MASTER_HOST.get(), BotSettings.SQL_MASTER_PORT.get(), BotSettings.SQL_DB.get(), BotSettings.SQL_MASTER_USER.get(), BotSettings.SQL_MASTER_PASS.get(), BotSettings.SQL_PREFIX.get()); DatabaseSettings slaveSettings = new DatabaseSettings(BotSettings.SQL_SLAVE_HOST.get(), BotSettings.SQL_SLAVE_PORT.get(), BotSettings.SQL_DB.get(), BotSettings.SQL_SLAVE_USER.get(), BotSettings.SQL_SLAVE_PASS.get(), BotSettings.SQL_PREFIX.get()); masterInfo = org.dreamexposure.novautils.database.DatabaseManager.connectToMySQL(masterSettings); slaveInfo = org.dreamexposure.novautils.database.DatabaseManager.connectToMySQL(slaveSettings); 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, true, this.getClass()); } } public void handleMigrations() { Map<String, String> placeholders = new HashMap<>(); placeholders.put("prefix", BotSettings.SQL_PREFIX.get()); try { Flyway flyway = Flyway.configure() .dataSource(masterInfo.getSource()) .cleanDisabled(true) .baselineOnMigrate(true) .table(BotSettings.SQL_PREFIX.get() + "schema_history") .placeholders(placeholders) .load(); int sm = flyway.migrate(); Logger.getLogger().debug("Migrations Successful, " + sm + " migrations applied!", true); } catch (Exception e) { Logger.getLogger().exception(null, "Migrations Failure", e, true, getClass()); System.exit(2); } } /** * Disconnects from the MySQL server if still connected. */ public void disconnectFromMySQL() { if (masterInfo != null && slaveInfo != null) { try { org.dreamexposure.novautils.database.DatabaseManager.disconnectFromMySQL(masterInfo); org.dreamexposure.novautils.database.DatabaseManager.disconnectFromMySQL(slaveInfo); System.out.println("Successfully disconnected from MySQL Database!"); } catch (Exception e) { Logger.getLogger().exception(null, "Disconnecting from MySQL failed.", e, true, this.getClass()); System.out.println("MySQL Connection may not have closed properly! Data may be invalidated!"); } } } public boolean updateAPIAccount(UserAPIAccount acc) { try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String tableName = String.format("%sapi", masterInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + tableName + " WHERE API_KEY = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, acc.getAPIKey()); 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 = masterConnection.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(); slaveConnection.close(); } else { //Data present, update. String update = "UPDATE " + tableName + " SET USER_ID = ?, BLOCKED = ?," + " USES = ? WHERE API_KEY = ?"; PreparedStatement ps = masterConnection.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(); slaveConnection.close(); } return true; } catch (SQLException e) { e.printStackTrace(); Logger.getLogger().exception(null, "Failed to update API account", e, true, this.getClass()); } return false; } public boolean updateSettings(GuildSettings settings) { guildSettingsCache.remove(settings.getGuildID()); guildSettingsCache.put(settings.getGuildID(), settings); if (settings.getPrivateKey().equalsIgnoreCase("N/a")) settings.setPrivateKey(KeyGenerator.csRandomAlphaNumericString(16)); try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String dataTableName = String.format("%sguild_settings", masterInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + dataTableName + " WHERE GUILD_ID = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, settings.getGuildID().asString()); 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 = masterConnection.prepareStatement(insertCommand); ps.setString(1, settings.getGuildID().asString()); 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(); slaveConnection.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 = masterConnection.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, settings.getGuildID().asString()); ps.executeUpdate(); ps.close(); statement.close(); slaveConnection.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, true, this.getClass()); e.printStackTrace(); } return false; } public boolean updateCalendar(CalendarData calData) { try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String calendarTableName = String.format("%scalendars", masterInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, calData.getGuildId().asString()); 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 = masterConnection.prepareStatement(insertCommand); ps.setString(1, calData.getGuildId().asString()); 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(); slaveConnection.close(); } else { //Data present, update. String update = "UPDATE " + calendarTableName + " SET CALENDAR_NUMBER = ?, CALENDAR_ID = ?," + " CALENDAR_ADDRESS = ?, EXTERNAL = ?" + " WHERE GUILD_ID = ?"; PreparedStatement ps = masterConnection.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, calData.getGuildId().asString()); ps.executeUpdate(); ps.close(); statement.close(); slaveConnection.close(); } return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to update/insert calendar data.", e, true, this.getClass()); } return false; } /** * Updates or Adds the specified {@link Announcement} Object to the database. * * @param announcement The announcement object to add to the database. * @return <code>true</code> if successful, else <code>false</code>. */ public boolean updateAnnouncement(Announcement announcement) { try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", masterInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, announcement.getAnnouncementId().toString()); 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 = masterConnection.prepareStatement(insertCommand); ps.setString(1, announcement.getAnnouncementId().toString()); ps.setString(2, announcement.getGuildId().asString()); 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(); slaveConnection.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 = masterConnection.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(); slaveConnection.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, true, this.getClass()); e.printStackTrace(); } return false; } public boolean updateEventData(EventData data) { try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String eventTableName = String.format("%sevents", masterInfo.getSettings().getPrefix()); if (data.getEventId().contains("_")) { data.setEventId(data.getEventId().split("_")[0]); } String query = "SELECT * FROM " + eventTableName + " WHERE EVENT_ID = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, data.getEventId()); 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 = masterConnection.prepareStatement(insertCommand); ps.setString(1, data.getGuildId().asString()); ps.setString(2, data.getEventId()); ps.setLong(3, data.getEventEnd()); ps.setString(4, data.getImageLink()); ps.executeUpdate(); ps.close(); statement.close(); slaveConnection.close(); } else { //Data present, update. String update = "UPDATE " + eventTableName + " SET IMAGE_LINK = ?, EVENT_END = ?" + " WHERE EVENT_ID = ?"; PreparedStatement ps = masterConnection.prepareStatement(update); ps.setString(1, data.getImageLink()); ps.setLong(2, data.getEventEnd()); ps.setString(3, data.getEventId()); ps.executeUpdate(); ps.close(); statement.close(); slaveConnection.close(); } return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to update/insert event data.", e, true, this.getClass()); } return false; } public boolean updateRsvpData(RsvpData data) { try (final Connection masterConnection = masterInfo.getSource().getConnection()) { String rsvpTableName = String.format("%srsvp", masterInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + rsvpTableName + " WHERE EVENT_ID = ?"; final Connection slaveConnection = slaveInfo.getSource().getConnection(); PreparedStatement statement = slaveConnection.prepareStatement(query); statement.setString(1, data.getEventId()); 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 = masterConnection.prepareStatement(insertCommand); ps.setString(1, data.getGuildId().asString()); 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(); slaveConnection.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 = masterConnection.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(); slaveConnection.close(); } return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to update/insert event data.", e, true, this.getClass()); } return false; } public UserAPIAccount getAPIAccount(String APIKey) { try (final Connection connection = slaveInfo.getSource().getConnection()) { String dataTableName = String.format("%sapi", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + dataTableName + " WHERE API_KEY = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, APIKey); 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, true, this.getClass()); } return null; } public GuildSettings getSettings(Snowflake guildId) { if (guildSettingsCache.containsKey(guildId)) return guildSettingsCache.get(guildId); boolean shouldStore = false; GuildSettings settings = new GuildSettings(guildId); try (final Connection connection = slaveInfo.getSource().getConnection()) { String dataTableName = String.format("%sguild_settings", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + dataTableName + " WHERE GUILD_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); ResultSet res = statement.executeQuery(); boolean hasStuff = res.next(); if (hasStuff && res.getString("GUILD_ID") != null) { shouldStore = true; 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(); } } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to get Guild Settings.", e, true, this.getClass()); } if (shouldStore) { guildSettingsCache.remove(guildId); //just incase its still there... guildSettingsCache.put(guildId, settings); } return settings; } public CalendarData getMainCalendar(Snowflake guildId) { CalendarData calData = new CalendarData(guildId, 1); try (final Connection connection = slaveInfo.getSource().getConnection()) { String calendarTableName = String.format("%scalendars", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); } return calData; } public CalendarData getCalendar(Snowflake guildId, int calendarNumber) { CalendarData calData = new CalendarData(guildId, calendarNumber); try (final Connection connection = slaveInfo.getSource().getConnection()) { String calendarTableName = String.format("%scalendars", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); } return calData; } public ArrayList<CalendarData> getAllCalendars(Snowflake guildId) { ArrayList<CalendarData> calendars = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String calendarTableName = String.format("%scalendars", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + calendarTableName + " WHERE GUILD_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); } return calendars; } public int getCalendarCount() { int amount = -1; try (final Connection connection = slaveInfo.getSource().getConnection()) { String calendarTableName = String.format("%scalendars", slaveInfo.getSettings().getPrefix()); String query = "SELECT COUNT(*) FROM " + calendarTableName + ";"; PreparedStatement statement = connection.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, true, this.getClass()); } return amount; } public EventData getEventData(Snowflake guildId, String eventId) { EventData data = new EventData(guildId); if (eventId.contains("_")) eventId = eventId.split("_")[0]; data.setEventId(eventId); try (final Connection connection = slaveInfo.getSource().getConnection()) { String eventTableName = String.format("%sevents", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + eventTableName + " WHERE GUILD_ID= ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); } return data; } public RsvpData getRsvpData(Snowflake guildId, String eventId) { RsvpData data = new RsvpData(guildId); data.setEventId(eventId); try (final Connection connection = slaveInfo.getSource().getConnection()) { String rsvpTableName = String.format("%srsvp", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + rsvpTableName + " WHERE GUILD_ID= ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); } return data; } /** * 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 <c>null</c>. */ public Announcement getAnnouncement(UUID announcementId, Snowflake guildId) { try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, announcementId.toString()); 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, true, this.getClass()); 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<Announcement> getAnnouncements(Snowflake guildId) { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); String query = "SELECT * FROM " + announcementTableName + " WHERE GUILD_ID = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, guildId.asString()); 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, true, this.getClass()); e.printStackTrace(); } return announcements; } public ArrayList<Announcement> getAnnouncements() { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); PreparedStatement stmt = connection.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")), Snowflake.of(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, true, this.getClass()); } return announcements; } public ArrayList<Announcement> getAnnouncements(AnnouncementType type) { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); PreparedStatement stmt = connection.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")), Snowflake.of(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, true, this.getClass()); } return announcements; } public ArrayList<Announcement> getEnabledAnnouncements() { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); PreparedStatement stmt = connection.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")), Snowflake.of(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, true, this.getClass()); } return announcements; } public ArrayList<Announcement> getEnabledAnnouncements(AnnouncementType type) { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); PreparedStatement stmt = connection.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")), Snowflake.of(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, true, this.getClass()); } return announcements; } public ArrayList<Announcement> getEnabledAnnouncements(Snowflake guildId) { ArrayList<Announcement> announcements = new ArrayList<>(); try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); PreparedStatement stmt = connection.prepareStatement("SELECT * FROM " + announcementTableName + " WHERE ENABLED = 1 AND GUILD_ID = ?"); stmt.setString(1, guildId.asString()); ResultSet res = stmt.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.fromValue(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 by type.", e, true, this.getClass()); } return announcements; } public int getAnnouncementCount() { int amount = -1; try (final Connection connection = slaveInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", slaveInfo.getSettings().getPrefix()); String query = "SELECT COUNT(*) FROM " + announcementTableName + ";"; PreparedStatement statement = connection.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, true, this.getClass()); } return amount; } /** * Deletes the specified announcement from the Database. * * @param announcementId The ID of the announcement to delete. * @return <code>true</code> if successful, else <code>false</code>. */ public boolean deleteAnnouncement(String announcementId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + announcementTableName + " WHERE ANNOUNCEMENT_ID = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, announcementId); preparedStmt.execute(); preparedStmt.close(); return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to delete announcement.", e, true, this.getClass()); } return false; } public boolean deleteAnnouncementsForEvent(Snowflake guildId, String eventId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String announcementTableName = String.format("%sannouncements", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + announcementTableName + " WHERE EVENT_ID = ? AND GUILD_ID = ? AND ANNOUNCEMENT_TYPE = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, eventId); preparedStmt.setString(2, guildId.asString()); 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, true, this.getClass()); } return false; } public boolean deleteEventData(String eventId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String eventTable = String.format("%sevents", masterInfo.getSettings().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 = connection.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, true, this.getClass()); } return false; } public boolean deleteAllEventData(Snowflake guildId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String eventTable = String.format("%sevents", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + eventTable + " WHERE GUILD_ID = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, guildId.asString()); preparedStmt.execute(); preparedStmt.close(); return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to delete all event data for guild.", e, true, this.getClass()); } return false; } public boolean deleteAllAnnouncementData(Snowflake guildId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String announcementTable = String.format("%sannouncements", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + announcementTable + " WHERE GUILD_ID = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, guildId.asString()); preparedStmt.execute(); preparedStmt.close(); return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to delete all announcements for guild.", e, true, this.getClass()); } return false; } public boolean deleteAllRSVPData(Snowflake guildId) { try (final Connection connection = masterInfo.getSource().getConnection()) { String rsvpTable = String.format("%srsvp", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + rsvpTable + " WHERE GUILD_ID = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, guildId.asString()); preparedStmt.execute(); preparedStmt.close(); return true; } catch (SQLException e) { Logger.getLogger().exception(null, "Failed to delete all RSVP data for guild.", e, true, this.getClass()); } return false; } public boolean deleteCalendar(CalendarData data) { try (final Connection connection = masterInfo.getSource().getConnection()) { String calendarTable = String.format("%scalendars", masterInfo.getSettings().getPrefix()); String query = "DELETE FROM " + calendarTable + " WHERE GUILD_ID = ? AND CALENDAR_ADDRESS = ?"; PreparedStatement preparedStmt = connection.prepareStatement(query); preparedStmt.setString(1, data.getGuildId().asString()); 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, true, this.getClass()); } return false; } public void clearCache() { guildSettingsCache.clear(); } }