diff --git a/API/API.iml b/API/API.iml deleted file mode 100644 index 0abd9d7e..00000000 --- a/API/API.iml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/API/pom.xml b/API/pom.xml deleted file mode 100644 index 5a43f655..00000000 --- a/API/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - - - com.cloudcraftgaming - DisCal - 2.0.0 - - - com.cloudcraftgaming.DisCal - API - - - \ No newline at end of file diff --git a/Bot/pom.xml b/Bot/pom.xml deleted file mode 100644 index 63cc9c89..00000000 --- a/Bot/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - - - com.cloudcraftgaming - DisCal - 2.0.0 - - - - UTF-8 - UTF-8 - - - com.cloudcraftgaming.DisCal - Bot - - - - - com.cloudcraftgaming.DisCal - API - 2.0.0 - compile - - - com.cloudcraftgaming.DisCal - Website - 2.0.0 - compile - - - - - ../target - DisCal-Bot - - - org.apache.maven.plugins - maven-shade-plugin - 3.1.1 - - - package - - shade - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - - true - com.cloudcraftgaming.discal.Main - - - - - - - \ No newline at end of file diff --git a/Website/pom.xml b/Website/pom.xml deleted file mode 100644 index b6e3b9d1..00000000 --- a/Website/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - - - UTF-8 - UTF-8 - - - - - com.cloudcraftgaming - DisCal - 2.0.0 - - - com.cloudcraftgaming.DisCal - Website - - - - com.cloudcraftgaming.DisCal - API - 2.0.0 - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index e2d4aafa..1ff614b7 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - pom com.cloudcraftgaming DisCal @@ -18,13 +17,6 @@ UTF-8 UTF-8 - - - API - Website - Bot - - 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>() { + }.getType(); + + Map map = new Gson().fromJson(fr, type); + langs.put(map.get("Language"), map); + + fr.close(); + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Failed to load lang files!", e, ReadFile.class, true); + } + return langs; + } +} \ No newline at end of file diff --git a/API/src/main/java/com/cloudcraftgaming/discal/api/message/MessageManager.java b/src/main/java/com/cloudcraftgaming/discal/api/message/MessageManager.java similarity index 100% rename from API/src/main/java/com/cloudcraftgaming/discal/api/message/MessageManager.java rename to src/main/java/com/cloudcraftgaming/discal/api/message/MessageManager.java diff --git a/src/main/java/com/cloudcraftgaming/discal/api/message/calendar/CalendarMessageFormatter.java b/src/main/java/com/cloudcraftgaming/discal/api/message/calendar/CalendarMessageFormatter.java new file mode 100644 index 00000000..c416ae83 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/message/calendar/CalendarMessageFormatter.java @@ -0,0 +1,76 @@ +package com.cloudcraftgaming.discal.api.message.calendar; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.PreCalendar; +import com.google.api.services.calendar.model.Calendar; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.util.EmbedBuilder; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CalendarMessageFormatter { + //TODO: Add support for multiple calendars. + public static String getCalendarLink(long guildId) { + return "https://www.discalbot.com/embed/calendar/" + guildId; + } + + public static EmbedObject getCalendarLinkEmbed(Calendar cal, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Calendar.Link.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.Calendar.Link.Summary", settings), cal.getSummary(), true); + try { + em.appendField(MessageManager.getMessage("Embed.Calendar.Link.Description", settings), cal.getDescription(), true); + } catch (NullPointerException | IllegalArgumentException e) { + //Some error, desc probably never set, just ignore no need to log. + } + em.appendField(MessageManager.getMessage("Embed.Calendar.Link.TimeZone", settings), cal.getTimeZone(), false); + em.withUrl(CalendarMessageFormatter.getCalendarLink(settings.getGuildID())); + em.withFooterText(MessageManager.getMessage("Embed.Calendar.Link.CalendarId", "%id%", cal.getId(), settings)); + em.withColor(56, 138, 237); + + return em.build(); + } + + /** + * Creates an EmbedObject for the PreCalendar. + * + * @param calendar The PreCalendar to create an EmbedObject for. + * @return The EmbedObject for the PreCalendar. + */ + public static EmbedObject getPreCalendarEmbed(PreCalendar calendar, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Calendar.Pre.Title", settings)); + if (calendar.getSummary() != null) + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.Summary", settings), calendar.getSummary(), true); + else + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.Summary", settings), "***UNSET***", true); + + if (calendar.getDescription() != null) + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.Description", settings), calendar.getDescription(), false); + else + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.Description", settings), "***UNSET***", false); + + if (calendar.getTimezone() != null) + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.TimeZone", settings), calendar.getTimezone(), true); + else + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.TimeZone", settings), "***UNSET***", true); + + if (calendar.isEditing()) + em.appendField(MessageManager.getMessage("Embed.Calendar.Pre.CalendarId", settings), calendar.getCalendarId(), false); + + + em.withFooterText(MessageManager.getMessage("Embed.Calendar.Pre.Key", settings)); + em.withColor(56, 138, 237); + + return em.build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/network/google/Authorization.java b/src/main/java/com/cloudcraftgaming/discal/api/network/google/Authorization.java new file mode 100644 index 00000000..ce0f7f0e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/network/google/Authorization.java @@ -0,0 +1,223 @@ +package com.cloudcraftgaming.discal.api.network.google; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.crypto.AESEncryption; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.message.calendar.CalendarMessageFormatter; +import com.cloudcraftgaming.discal.api.object.BotSettings; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.json.google.AuthPollResponseError; +import com.cloudcraftgaming.discal.api.object.json.google.AuthPollResponseGrant; +import com.cloudcraftgaming.discal.api.object.json.google.AuthRefreshResponse; +import com.cloudcraftgaming.discal.api.object.json.google.CodeResponse; +import com.cloudcraftgaming.discal.api.object.network.google.ClientData; +import com.cloudcraftgaming.discal.api.object.network.google.Poll; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.client.http.HttpStatusCodes; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.CalendarScopes; +import com.google.api.services.calendar.model.CalendarListEntry; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.mashape.unirest.http.JsonNode; +import com.mashape.unirest.http.Unirest; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.EmbedBuilder; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.List; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class Authorization { + private static Authorization instance; + private ClientData clientData; + + private Authorization() { + } //Prevent initialization. + + public static Authorization getAuth() { + if (instance == null) + instance = new Authorization(); + + return instance; + } + + public void init() { + clientData = new ClientData(BotSettings.GOOGLE_CLIENT_ID.get(), BotSettings.GOOGLE_CLIENT_SECRET.get()); + } + + public void requestCode(MessageReceivedEvent event, GuildSettings settings) { + try { + String body = "client_id=" + clientData.getClientId() + "&scope=" + CalendarScopes.CALENDAR; + + com.mashape.unirest.http.HttpResponse response = Unirest.post("https://accounts.google.com/o/oauth2/device/code").header("Content-Type", "application/x-www-form-urlencoded").body(body).asJson(); + + if (response.getStatus() == HttpStatusCodes.STATUS_CODE_OK) { + Type type = new TypeToken() { + }.getType(); + CodeResponse cr = new Gson().fromJson(response.getBody().toString(), type); + + //Send DM to user with code. + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.AddCalendar.Code.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.AddCalendar.Code.Code", settings), cr.user_code, true); + em.withFooterText(MessageManager.getMessage("Embed.AddCalendar.Code.Footer", settings)); + + em.withUrl(cr.verification_url); + em.withColor(36, 153, 153); + + IUser user = event.getAuthor(); + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Code.Request.Success", settings), em.build(), user); + + //Start timer to poll Google Cal for auth + Poll poll = new Poll(user, event.getGuild()); + + poll.setDevice_code(cr.device_code); + poll.setRemainingSeconds(cr.expires_in); + poll.setExpires_in(cr.expires_in); + poll.setInterval(cr.interval); + pollForAuth(poll); + } else { + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Code.Request.Failure.NotOkay", settings), event.getAuthor()); + + Logger.getLogger().debug(event.getAuthor(), "Error requesting access token.", "Status code: " + response.getStatus() + " | " + response.getStatusText() + " | " + response.getBody().toString(), this.getClass(), true); + } + } catch (Exception e) { + //Failed, report issue to dev. + Logger.getLogger().exception(event.getAuthor(), "Failed to request Google Access Code", e, this.getClass(), true); + IUser u = event.getAuthor(); + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Code.Request.Failure.Unknown", settings), u); + } + } + + public String requestNewAccessToken(GuildSettings settings, AESEncryption encryption) { + try { + String body = "client_id=" + clientData.getClientId() + "&client_secret=" + clientData.getClientSecret() + "&refresh_token=" + encryption.decrypt(settings.getEncryptedRefreshToken()) + "&grant_type=refresh_token"; + + com.mashape.unirest.http.HttpResponse httpResponse = Unirest.post("https://www.googleapis.com/oauth2/v4/token").header("Content-Type", "application/x-www-form-urlencoded").body(body).asJson(); + + if (httpResponse.getStatus() == HttpStatusCodes.STATUS_CODE_OK) { + + Type type = new TypeToken() { + }.getType(); + AuthRefreshResponse response = new Gson().fromJson(httpResponse.getBody().toString(), type); + + //Update Db data. + settings.setEncryptedAccessToken(encryption.encrypt(response.access_token)); + DatabaseManager.getManager().updateSettings(settings); + + //Okay, we can return the access token to be used when this method is called. + return response.access_token; + } else { + //Failed to get OK. Send debug info. + Logger.getLogger().debug(null, "Error requesting new access token.", "Status code: " + httpResponse.getStatus() + " | " + httpResponse.getStatusText() + " | " + httpResponse.getBody().toString(), this.getClass(), true); + return null; + } + + } catch (Exception e) { + //Error occurred, lets just log it and return null. + Logger.getLogger().exception(null, "Failed to request new access token.", e, this.getClass(), true); + return null; + } + } + + void pollForAuth(Poll poll) { + GuildSettings settings = DatabaseManager.getManager().getSettings(poll.getGuild().getLongID()); + try { + String body = "client_id=" + clientData.getClientId() + "&client_secret=" + clientData.getClientSecret() + "&code=" + poll.getDevice_code() + "&grant_type=http://oauth.net/grant_type/device/1.0"; + + //Execute + com.mashape.unirest.http.HttpResponse response = Unirest.post("https://www.googleapis.com/oauth2/v4/token").header("Content-Type", "application/x-www-form-urlencoded").body(body).asJson(); + + //Handle response. + if (response.getStatus() == 403) { + //Handle access denied + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Failure.Deny", settings), poll.getUser()); + } else if (response.getStatus() == 400) { + try { + //See if auth is pending, if so, just reschedule. + Type type = new TypeToken() { + }.getType(); + AuthPollResponseError apre = new Gson().fromJson(response.getBody().toString(), type); + + if (apre.error.equalsIgnoreCase("authorization_pending")) { + //Response pending + PollManager.getManager().scheduleNextPoll(poll); + } else if (apre.error.equalsIgnoreCase("expired_token")) { + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Failure.Expired", settings), poll.getUser()); + } else { + MessageManager.sendDirectMessage(MessageManager.getMessage("Notification.Error.Network", settings), poll.getUser()); + Logger.getLogger().debug(poll.getUser(), "Poll Failure!", "Status code: " + response.getStatus() + " | " + response.getStatusText() + " | " + response.getBody().toString(), this.getClass(), true); + } + } catch (Exception e) { + //Auth is not pending, error occurred. + Logger.getLogger().exception(poll.getUser(), "Failed to poll for authorization to google account.", e, this.getClass(), true); + Logger.getLogger().debug(poll.getUser(), "More info on failure", "Status code: " + response.getStatus() + " | " + response.getStatusText() + " | " + response.getBody().toString(), this.getClass(), true); + MessageManager.sendDirectMessage(MessageManager.getMessage("Notification.Error.Network", settings), poll.getUser()); + } + } else if (response.getStatus() == 429) { + //We got rate limited... oops. Let's just poll half as often. + poll.setInterval(poll.getInterval() * 2); + PollManager.getManager().scheduleNextPoll(poll); + } else if (response.getStatus() == HttpStatusCodes.STATUS_CODE_OK) { + //Access granted + Type type = new TypeToken() { + }.getType(); + AuthPollResponseGrant aprg = new Gson().fromJson(response.getBody().toString(), type); + + //Save credentials securely. + GuildSettings gs = DatabaseManager.getManager().getSettings(poll.getGuild().getLongID()); + AESEncryption encryption = new AESEncryption(gs); + gs.setEncryptedAccessToken(encryption.encrypt(aprg.access_token)); + gs.setEncryptedRefreshToken(encryption.encrypt(aprg.refresh_token)); + gs.setUseExternalCalendar(true); + DatabaseManager.getManager().updateSettings(gs); + + try { + Calendar service = CalendarAuth.getCalendarService(gs); + List items = service.calendarList().list().setMinAccessRole("writer").execute().getItems(); + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Success", settings), poll.getUser()); + for (CalendarListEntry i: items) { + if (!i.isDeleted()) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.AddCalendar.List.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.AddCalendar.List.Name", settings), i.getSummary(), false); + em.appendField(MessageManager.getMessage("Embed.AddCalendar.List.TimeZone", settings), i.getTimeZone(), false); + em.appendField(MessageManager.getMessage("Embed.AddCalendar.List.ID", settings), i.getId(), false); + + em.withUrl(CalendarMessageFormatter.getCalendarLink(settings.getGuildID())); + em.withColor(56, 138, 237); + MessageManager.sendDirectMessage(em.build(), poll.getUser()); + } + } + //Response will be handled in guild, and will check. We already saved the tokens anyway. + } catch (IOException e1) { + //Failed to get calendars list and check for calendars. + Logger.getLogger().exception(poll.getUser(), "Failed to list calendars from external account!", e1, this.getClass(), true); + + MessageManager.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Failure.ListCalendars", settings), poll.getUser()); + } + } else { + //Unknown network error... + MessageManager.sendDirectMessage(MessageManager.getMessage("Notification.Error.Network", settings), poll.getUser()); + Logger.getLogger().debug(poll.getUser(), "Network error; poll failure", "Status code: " + response.getStatus() + " | " + response.getStatusText() + " | " + response.getBody().toString(), this.getClass(), true); + } + } catch (Exception e) { + //Handle exception. + Logger.getLogger().exception(poll.getUser(), "Failed to poll for authorization to google account", e, this.getClass(), true); + MessageManager.sendDirectMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), poll.getUser()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/network/google/PollManager.java b/src/main/java/com/cloudcraftgaming/discal/api/network/google/PollManager.java new file mode 100644 index 00000000..7a139eb2 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/network/google/PollManager.java @@ -0,0 +1,41 @@ +package com.cloudcraftgaming.discal.api.network.google; + +import com.cloudcraftgaming.discal.api.object.network.google.Poll; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class PollManager { + private static PollManager instance; + + private Timer timer; + + //Prevent initialization. + private PollManager() { + //Use daemon because this is a util timer and there is no reason to keep the program running when this is polling Google, just assume it timed out and re-auth if all else fails. + timer = new Timer(true); + } + + public static PollManager getManager() { + if (instance == null) + instance = new PollManager(); + + return instance; + } + + //Timer methods. + void scheduleNextPoll(Poll poll) { + timer.schedule(new TimerTask() { + @Override + public void run() { + poll.setRemainingSeconds(poll.getRemainingSeconds() - poll.getInterval()); + Authorization.getAuth().pollForAuth(poll); + } + }, 1000 * poll.getInterval()); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/BotSettings.java b/src/main/java/com/cloudcraftgaming/discal/api/object/BotSettings.java new file mode 100644 index 00000000..7e935248 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/BotSettings.java @@ -0,0 +1,34 @@ +package com.cloudcraftgaming.discal.api.object; + +import java.util.Properties; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public enum BotSettings { + SQL_HOST, SQL_USER, SQL_PASSWORD, + SQL_DB, SQL_PORT, SQL_PREFIX, TOKEN, SECRET, ID, + LANG_PATH, PW_TOKEN, DBO_TOKEN, UPDATE_SITES, GOOGLE_CLIENT_ID, + GOOGLE_CLIENT_SECRET, RUN_API, TIME_OUT, PORT, ACCEPT_CLI, REDIR_URI, REDIR_URL, LOG_FOLDER; + + private String val; + + BotSettings() { + } + + public static void init(Properties properties) { + for (BotSettings s: values()) { + s.set(properties.getProperty(s.name())); + } + } + + public String get() { + return val; + } + + public void set(String _val) { + val = _val; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/GuildSettings.java b/src/main/java/com/cloudcraftgaming/discal/api/object/GuildSettings.java new file mode 100644 index 00000000..dea868b3 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/GuildSettings.java @@ -0,0 +1,208 @@ +package com.cloudcraftgaming.discal.api.object; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class GuildSettings { + private final long guildID; + + private boolean externalCalendar; + private String privateKey; + + private String encryptedAccessToken; + private String encryptedRefreshToken; + + private String controlRole; + private String discalChannel; + + private boolean simpleAnnouncements; + private String lang; + private String prefix; + + private boolean patronGuild; + private boolean devGuild; + private int maxCalendars; + + private boolean twelveHour; + private boolean branded; + + private final ArrayList dmAnnouncements = new ArrayList<>(); + + public GuildSettings(long _guildId) { + guildID = _guildId; + + externalCalendar = false; + privateKey = "N/a"; + + encryptedAccessToken = "N/a"; + encryptedRefreshToken = "N/a"; + + controlRole = "everyone"; + discalChannel = "all"; + + simpleAnnouncements = false; + lang = "ENGLISH"; + prefix = "!"; + + patronGuild = false; + devGuild = false; + maxCalendars = 1; + + twelveHour = true; + } + + //Getters + public long getGuildID() { + return guildID; + } + + public boolean useExternalCalendar() { + return externalCalendar; + } + + public String getPrivateKey() { + return privateKey; + } + + public String getEncryptedAccessToken() { + return encryptedAccessToken; + } + + public String getEncryptedRefreshToken() { + return encryptedRefreshToken; + } + + public String getControlRole() { + return controlRole; + } + + public String getDiscalChannel() { + return discalChannel; + } + + public boolean usingSimpleAnnouncements() { + return simpleAnnouncements; + } + + public String getLang() { + return lang; + } + + public String getPrefix() { + return prefix; + } + + public boolean isPatronGuild() { + return patronGuild; + } + + public boolean isDevGuild() { + return devGuild; + } + + public int getMaxCalendars() { + return maxCalendars; + } + + public boolean useTwelveHour() { + return twelveHour; + } + + public boolean isBranded() { + return branded; + } + + public ArrayList getDmAnnouncements() { + return dmAnnouncements; + } + + public String getDmAnnouncementsString() { + StringBuilder users = new StringBuilder(); + int i = 0; + for (String sub: dmAnnouncements) { + if (i == 0) { + users = new StringBuilder(sub); + } else { + users.append(",").append(sub); + } + i++; + } + return users.toString(); + } + + //Dumb getters so that Tymeleaf plays nice... + public boolean isExternalCalendar() { + return externalCalendar; + } + + public boolean isSimpleAnnouncements() { + return simpleAnnouncements; + } + + //Setters + public void setUseExternalCalendar(boolean _useExternal) { + externalCalendar = _useExternal; + } + + public void setPrivateKey(String _privateKey) { + privateKey = _privateKey; + } + + public void setEncryptedAccessToken(String _access) { + encryptedAccessToken = _access; + } + + public void setEncryptedRefreshToken(String _refresh) { + encryptedRefreshToken = _refresh; + } + + public void setControlRole(String _controlRole) { + controlRole = _controlRole; + } + + public void setDiscalChannel(String _discalChannel) { + discalChannel = _discalChannel; + } + + public void setSimpleAnnouncements(boolean _simpleAnnouncements) { + simpleAnnouncements = _simpleAnnouncements; + } + + public void setLang(String _lang) { + lang = _lang; + } + + public void setPrefix(String _prefix) { + prefix = _prefix; + } + + public void setPatronGuild(boolean _patronGuild) { + patronGuild = _patronGuild; + } + + public void setDevGuild(boolean _devGuild) { + devGuild = _devGuild; + } + + public void setMaxCalendars(Integer _maxCalendars) { + maxCalendars = _maxCalendars; + } + + public void setTwelveHour(boolean _twelveHour) { + twelveHour = _twelveHour; + } + + public void setBranded(boolean _branded) { + branded = _branded; + } + + public void setDmAnnouncementsFromString(String userList) { + String[] subs = userList.split(","); + Collections.addAll(dmAnnouncements, subs); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/Announcement.java b/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/Announcement.java new file mode 100644 index 00000000..bdd884d6 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/Announcement.java @@ -0,0 +1,392 @@ +package com.cloudcraftgaming.discal.api.object.announcement; + +import com.cloudcraftgaming.discal.api.enums.announcement.AnnouncementType; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import sx.blah.discord.handle.obj.IMessage; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.UUID; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +@SuppressWarnings("WeakerAccess") +public class Announcement { + private final UUID announcementId; + private final long guildId; + + private final ArrayList subscriberRoleIds = new ArrayList<>(); + private final ArrayList subscriberUserIds = new ArrayList<>(); + + private String announcementChannelId; + private AnnouncementType type; + private String eventId; + private EventColor eventColor; + private int hoursBefore; + private int minutesBefore; + private String info; + + private boolean enabled; + private boolean infoOnly; + + private IMessage creatorMessage; + + private boolean editing; + + private long lastEdit; + + /** + * Use this constructor when creating NEW announcements!!! + * + * @param _guildId The ID of the Guild this announcement belongs to. + */ + public Announcement(long _guildId) { + guildId = _guildId; + announcementId = UUID.randomUUID(); + announcementChannelId = "N/a"; + eventId = "N/a"; + eventColor = EventColor.RED; + type = AnnouncementType.UNIVERSAL; + hoursBefore = 0; + minutesBefore = 0; + info = "None"; + enabled = true; + infoOnly = false; + + lastEdit = System.currentTimeMillis(); + } + + /** + * Use this constructor when retrieving date from the database!!! + * + * @param _announcementId The ID of the announcement object. + * @param _guildId The ID of the guild the announcement belongs to. + */ + public Announcement(UUID _announcementId, long _guildId) { + announcementId = _announcementId; + guildId = _guildId; + announcementChannelId = "N/a"; + eventId = "N/a"; + eventColor = EventColor.RED; + type = AnnouncementType.UNIVERSAL; + hoursBefore = 0; + minutesBefore = 0; + info = "None"; + enabled = true; + infoOnly = false; + + editing = false; + lastEdit = System.currentTimeMillis(); + } + + @SuppressWarnings("CopyConstructorMissesField") + public Announcement(Announcement from) { + guildId = from.getGuildId(); + announcementId = UUID.randomUUID(); + announcementChannelId = from.getAnnouncementChannelId(); + eventId = from.getEventId(); + eventColor = from.getEventColor(); + type = from.getAnnouncementType(); + hoursBefore = from.getHoursBefore(); + minutesBefore = from.getMinutesBefore(); + info = from.getInfo(); + enabled = from.isEnabled(); + infoOnly = from.isInfoOnly(); + + setSubscriberRoleIdsFromString(from.getSubscriberRoleIdString()); + setSubscriberUserIdsFromString(from.getSubscriberUserIdString()); + + editing = false; + lastEdit = System.currentTimeMillis(); + } + + public Announcement(Announcement from, boolean copyId) { + guildId = from.getGuildId(); + if (copyId) { + announcementId = from.getAnnouncementId(); + } else { + announcementId = UUID.randomUUID(); + } + announcementChannelId = from.getAnnouncementChannelId(); + eventId = from.getEventId(); + eventColor = from.getEventColor(); + type = from.getAnnouncementType(); + hoursBefore = from.getHoursBefore(); + minutesBefore = from.getMinutesBefore(); + info = from.getInfo(); + enabled = from.isEnabled(); + infoOnly = from.isInfoOnly(); + + setSubscriberRoleIdsFromString(from.getSubscriberRoleIdString()); + setSubscriberUserIdsFromString(from.getSubscriberUserIdString()); + + editing = false; + lastEdit = System.currentTimeMillis(); + } + + //Getters + + /** + * Gets the ID of the announcement. + * + * @return The ID of the announcement. + */ + public UUID getAnnouncementId() { + return announcementId; + } + + /** + * Gets the Guild ID the announcement belongs to. + * + * @return The Guild ID the announcement belongs to. + */ + public long getGuildId() { + return guildId; + } + + /** + * Gets the ID of the channel the announcement is to be broadcast in. + * + * @return The ID of the channel the announcement is to be broadcast in. + */ + public String getAnnouncementChannelId() { + return announcementChannelId; + } + + /** + * Gets the IDs of Roles that are subscribed to the announcement. + * + * @return The IDs fo the Roles that are subscribed to the announcement. + */ + public ArrayList getSubscriberRoleIds() { + return subscriberRoleIds; + } + + /** + * Gets the IDs of the Users that are subscribed to the announcement. + * + * @return The IDs of the Users that are subscribed to the announcement. + */ + public ArrayList getSubscriberUserIds() { + return subscriberUserIds; + } + + /** + * Gets a string of ALL roles that are subscribed to the announcement. + * + * @return A string of roles that are subscribed to the announcement. + */ + public String getSubscriberRoleIdString() { + StringBuilder subs = new StringBuilder(); + Integer i = 0; + for (String sub: subscriberRoleIds) { + if (i == 0) { + subs = new StringBuilder(sub); + } else { + subs.append(",").append(sub); + } + i++; + } + return subs.toString(); + } + + /** + * Gets a string of ALL users that are subscribed to the announcement. + * + * @return A string of users that are subscribed to the announcement. + */ + public String getSubscriberUserIdString() { + StringBuilder subs = new StringBuilder(); + Integer i = 0; + for (String sub: subscriberUserIds) { + if (i == 0) { + subs = new StringBuilder(sub); + } else { + subs.append(",").append(sub); + } + i++; + } + return subs.toString(); + } + + /** + * Get the type of announcement this is. + * + * @return The type of announcement this is. + */ + public AnnouncementType getAnnouncementType() { + if (type != null) + return type; + else + return AnnouncementType.UNIVERSAL; + } + + /** + * Gets the Event ID linked to the announcement, if any. + * + * @return The Event ID linked to the announcement. + */ + public String getEventId() { + return eventId; + } + + public EventColor getEventColor() { + return eventColor; + } + + /** + * Gets the amount of hours before the event to announce. + * + * @return The amount of hours before the event to announce. + */ + public int getHoursBefore() { + return hoursBefore; + } + + /** + * Gets the amount of minutes before the event to announce. + * + * @return The amount of minutes before the event to announce. + */ + public int getMinutesBefore() { + return minutesBefore; + } + + /** + * Gets extra info for the announcement. + * + * @return Extra info for the announcement. + */ + public String getInfo() { + return info; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean isInfoOnly() { + return infoOnly; + } + + public IMessage getCreatorMessage() { + return creatorMessage; + } + + public boolean isEditing() { + return editing; + } + + public long getLastEdit() { + return lastEdit; + } + + //Setters + + /** + * Sets the ID of the channel to announce in. + * + * @param _announcementChannelId The ID of the channel to announce in. + */ + public void setAnnouncementChannelId(String _announcementChannelId) { + announcementChannelId = _announcementChannelId; + } + + /** + * Sets the type of announcement this is. + * + * @param _type The type of the announcement this is. + */ + public void setAnnouncementType(AnnouncementType _type) { + type = _type; + } + + /** + * Sets the ID of the event to announce for. + * + * @param _eventId The ID of the event to announce for. + */ + public void setEventId(String _eventId) { + eventId = _eventId; + } + + public void setEventColor(EventColor _eventColor) { + eventColor = _eventColor; + } + + /** + * Sets the hours before the event to announce for. + * + * @param _hoursBefore The hours before the event to announce for. + */ + public void setHoursBefore(Integer _hoursBefore) { + hoursBefore = _hoursBefore; + } + + /** + * Sets the minutes before the event to announce for. + * + * @param _minutesBefore The minutes before the event to announce for. + */ + public void setMinutesBefore(int _minutesBefore) { + minutesBefore = _minutesBefore; + } + + public void setInfo(String _info) { + info = _info; + } + + public void setEnabled(boolean _enabled) { + enabled = _enabled; + } + + public void setInfoOnly(boolean _infoOnly) { + infoOnly = _infoOnly; + } + + /** + * Sets the subscribers of the announcement from a String. + * + * @param subList String value of subscribing roles. + */ + public void setSubscriberRoleIdsFromString(String subList) { + String[] subs = subList.split(","); + Collections.addAll(subscriberRoleIds, subs); + } + + /** + * Sets the subscribers of the announcement from a string. + * + * @param subList String value of subscribing users. + */ + public void setSubscriberUserIdsFromString(String subList) { + String[] subs = subList.split(","); + Collections.addAll(subscriberUserIds, subs); + } + + public void setCreatorMessage(IMessage _message) { + creatorMessage = _message; + } + + public void setEditing(boolean _editing) { + editing = _editing; + } + + public void setLastEdit(long _lastEdit) { + lastEdit = _lastEdit; + } + + //Booleans/Checkers + + /** + * Checks if the announcement has all required values to be entered into a database. + * + * @return true if all values are present, else false. + */ + public Boolean hasRequiredValues() { + return (minutesBefore != 0 || hoursBefore != 0) && !(type.equals(AnnouncementType.SPECIFIC) && eventId.equalsIgnoreCase("N/a")) && !announcementChannelId.equalsIgnoreCase("N/a"); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/AnnouncementCreatorResponse.java b/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/AnnouncementCreatorResponse.java new file mode 100644 index 00000000..e796d654 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/announcement/AnnouncementCreatorResponse.java @@ -0,0 +1,63 @@ +package com.cloudcraftgaming.discal.api.object.announcement; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class AnnouncementCreatorResponse { + private final boolean successful; + + private Announcement announcement; + + /** + * Creates an AnnouncementCreatorResponse. + * + * @param _successful Whether or not the creator was successful. + */ + public AnnouncementCreatorResponse(boolean _successful) { + successful = _successful; + } + + /** + * Creates an AnnouncementCreatorResponse. + * + * @param _successful Whether or not the creator was successful. + * @param _announcement The announcement involved. + */ + public AnnouncementCreatorResponse(boolean _successful, Announcement _announcement) { + successful = _successful; + announcement = _announcement; + } + + //Getters + + /** + * Gets whether or not the creator was successful. + * + * @return Whether or not the creator was successful. + */ + public boolean isSuccessful() { + return successful; + } + + /** + * Gets the announcement involved. + * + * @return The Announcement involved. + */ + public Announcement getAnnouncement() { + return announcement; + } + + //Setters + + /** + * Sets the announcement involved. + * + * @param _announcement The Announcement involved. + */ + public void setAnnouncement(Announcement _announcement) { + announcement = _announcement; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarCreatorResponse.java b/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarCreatorResponse.java new file mode 100644 index 00000000..219b28a0 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarCreatorResponse.java @@ -0,0 +1,84 @@ +package com.cloudcraftgaming.discal.api.object.calendar; + +import com.google.api.services.calendar.model.Calendar; +import sx.blah.discord.handle.obj.IMessage; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CalendarCreatorResponse { + private final boolean successful; + + private boolean edited; + private IMessage creatorMessage; + private Calendar calendar; + + /** + * Creates a new response. + * + * @param _successful Whether or not the creation was successful. + */ + public CalendarCreatorResponse(boolean _successful) { + successful = _successful; + } + + /** + * Creates a new response. + * + * @param _successful Whether or not the creation was successful. + * @param _calendar The calendar created. + */ + public CalendarCreatorResponse(boolean _successful, Calendar _calendar) { + successful = _successful; + calendar = _calendar; + } + + //Getters + + /** + * Whether or not the creation was successful. + * + * @return true if successful, else false. + */ + public boolean isSuccessful() { + return successful; + } + + /** + * The calendar involved. Can be null. + * + * @return The calendar involved, may be null. + */ + public Calendar getCalendar() { + return calendar; + } + + public boolean isEdited() { + return edited; + } + + public IMessage getCreatorMessage() { + return creatorMessage; + } + + //Setters + + /** + * Sets the calendar involved. + * + * @param _calendar The calendar involved. + */ + public void setCalendar(Calendar _calendar) { + calendar = _calendar; + } + + public void setEdited(boolean _edit) { + edited = _edit; + } + + public void setCreatorMessage(IMessage msg) { + creatorMessage = msg; + } +} \ No newline at end of file diff --git a/API/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarData.java b/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarData.java similarity index 100% rename from API/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarData.java rename to src/main/java/com/cloudcraftgaming/discal/api/object/calendar/CalendarData.java diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/PreCalendar.java b/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/PreCalendar.java new file mode 100644 index 00000000..1d94e6ce --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/calendar/PreCalendar.java @@ -0,0 +1,165 @@ +package com.cloudcraftgaming.discal.api.object.calendar; + +import com.google.api.services.calendar.model.Calendar; +import sx.blah.discord.handle.obj.IMessage; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class PreCalendar { + private final long guildId; + + private String summary; + private String description; + private String timezone; + + private boolean editing; + private String calendarId; + + private IMessage creatorMessage; + + private long lastEdit; + + /** + * Creates a new PreCalendar for the Guild. + * + * @param _guildId The ID of the guild. + * @param _summary The summary/name of the calendar. + */ + public PreCalendar(long _guildId, String _summary) { + guildId = _guildId; + summary = _summary; + + editing = false; + + lastEdit = System.currentTimeMillis(); + } + + public PreCalendar(long _guildId, Calendar calendar) { + guildId = _guildId; + summary = calendar.getSummary(); + + if (calendar.getDescription() != null) + description = calendar.getDescription(); + + if (calendar.getTimeZone() != null) + timezone = calendar.getTimeZone(); + + + editing = false; + + lastEdit = System.currentTimeMillis(); + } + + //Getters + + /** + * Gets the ID of the guild this PreCalendar belongs to. + * + * @return The ID of the guild this PreCalendar belongs to. + */ + public long getGuildId() { + return guildId; + } + + /** + * Gets the summary or name of the calendar. + * + * @return The summary or name of the calendar. + */ + public String getSummary() { + return summary; + } + + /** + * Gets the description of the calendar. + * + * @return The description of the calendar. + */ + public String getDescription() { + return description; + } + + /** + * Gets the Timezone of the calendar. + * + * @return The Timezone of the calendar. + */ + public String getTimezone() { + return timezone; + } + + public boolean isEditing() { + return editing; + } + + public String getCalendarId() { + return calendarId; + } + + public IMessage getCreatorMessage() { + return creatorMessage; + } + + public long getLastEdit() { + return lastEdit; + } + + //Setters + + /** + * Sets the summary/name of the calendar. + * + * @param _summary The summary/name of the calendar. + */ + public void setSummary(String _summary) { + summary = _summary; + } + + /** + * Sets the description of the calendar. + * + * @param _description The description of the calendar. + */ + public void setDescription(String _description) { + description = _description; + } + + /** + * Sets the timezone of the calendar. + * + * @param _timezone The timezone of the calendar. + */ + public void setTimezone(String _timezone) { + timezone = _timezone; + } + + public void setEditing(boolean _editing) { + editing = _editing; + } + + public void setCalendarId(String _id) { + calendarId = _id; + } + + public void setCreatorMessage(IMessage _message) { + creatorMessage = _message; + } + + public void setLastEdit(long _lastEdit) { + lastEdit = _lastEdit; + } + + //Booleans/Checkers + + /** + * Checks if the calendar has all required data in order to be created. + * + * @return true if required data set, otherwise false. + */ + public boolean hasRequiredValues() { + return summary != null && timezone != null; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/command/CommandInfo.java b/src/main/java/com/cloudcraftgaming/discal/api/object/command/CommandInfo.java new file mode 100644 index 00000000..98b56541 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/command/CommandInfo.java @@ -0,0 +1,46 @@ +package com.cloudcraftgaming.discal.api.object.command; + +import java.util.HashMap; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CommandInfo { + private final String name; + private String description; + private String example; + + private HashMap subCommands = new HashMap<>(); + + public CommandInfo(String _name) { + name = _name; + } + + //Getters + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getExample() { + return example; + } + + public HashMap getSubCommands() { + return subCommands; + } + + //Setters + public void setDescription(String _description) { + description = _description; + } + + public void setExample(String _example) { + example = _example; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventCreatorResponse.java b/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventCreatorResponse.java new file mode 100644 index 00000000..8de6db8f --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventCreatorResponse.java @@ -0,0 +1,85 @@ +package com.cloudcraftgaming.discal.api.object.event; + +import com.google.api.services.calendar.model.Event; +import sx.blah.discord.handle.obj.IMessage; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class EventCreatorResponse { + private final boolean successful; + + private IMessage creatorMessage; + + private Event event; + private boolean edited; + + /** + * Creates a new Response. + * + * @param _successful Whether or not the Creator was successful. + */ + public EventCreatorResponse(boolean _successful) { + successful = _successful; + } + + /** + * Creates a new Response. + * + * @param _successful Whether or not the Creator was successful. + * @param _event The Event that was created. + */ + public EventCreatorResponse(boolean _successful, Event _event) { + successful = _successful; + event = _event; + edited = false; + } + + //Getters + + /** + * Whether or not the creator was successful. + * + * @return true if successful, else false. + */ + public boolean isSuccessful() { + return successful; + } + + public IMessage getCreatorMessage() { + return creatorMessage; + } + + public boolean isEdited() { + return edited; + } + + /** + * Gets the event that was created. + * + * @return The event that was created. + */ + public Event getEvent() { + return event; + } + + //Setters + public void setCreatorMessage(IMessage _creatorMessage) { + creatorMessage = _creatorMessage; + } + + /** + * Sets the event that was created. + * + * @param _event The event that was created. + */ + public void setEvent(Event _event) { + event = _event; + } + + public void setEdited(boolean _edited) { + edited = _edited; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventData.java b/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventData.java new file mode 100644 index 00000000..a33b94ee --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/event/EventData.java @@ -0,0 +1,55 @@ +package com.cloudcraftgaming.discal.api.object.event; + +import javax.annotation.Nullable; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class EventData { + private final long guildId; + + private String eventId; + private long eventEnd; + private String imageLink; + + public EventData(long _guildId) { + guildId = _guildId; + } + + //Getters + public long getGuildId() { + return guildId; + } + + public String getEventId() { + return eventId; + } + + public long getEventEnd() { + return eventEnd; + } + + public String getImageLink() { + return imageLink; + } + + //Setters + public void setEventId(String _eventId) { + eventId = _eventId; + } + + public void setEventEnd(long _eventEnd) { + eventEnd = _eventEnd; + } + + public void setImageLink(@Nullable String _link) { + imageLink = _link; + } + + //Boolean/Checkers + public boolean shouldBeSaved() { + return imageLink != null; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/event/PreEvent.java b/src/main/java/com/cloudcraftgaming/discal/api/object/event/PreEvent.java new file mode 100644 index 00000000..bf606ecd --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/event/PreEvent.java @@ -0,0 +1,373 @@ +package com.cloudcraftgaming.discal.api.object.event; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.utils.TimeUtils; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.client.util.DateTime; +import com.google.api.services.calendar.model.Calendar; +import com.google.api.services.calendar.model.Event; +import com.google.api.services.calendar.model.EventDateTime; +import sx.blah.discord.handle.obj.IMessage; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class PreEvent { + private final long guildId; + private final String eventId; + + private String summary; + private String description; + private EventDateTime startDateTime; + private EventDateTime endDateTime; + + private EventDateTime viewableStartDate; + private EventDateTime viewableEndDate; + + private String timeZone; + + private EventColor color; + + private String location; + + private boolean recur; + private Recurrence recurrence; + + private EventData eventData; + + private boolean editing; + + private IMessage creatorMessage; + + private long lastEdit; + + + /** + * Creates a new PreEvent for the specified Guild. + * + * @param _guildId The ID of the guild. + */ + public PreEvent(long _guildId) { + guildId = _guildId; + eventId = "N/a"; + + timeZone = "Unknown"; + + color = EventColor.NONE; + + recur = false; + recurrence = new Recurrence(); + + eventData = new EventData(guildId); + + editing = false; + lastEdit = System.currentTimeMillis(); + } + + public PreEvent(long _guildId, Event e) { + guildId = _guildId; + eventId = e.getId(); + + color = EventColor.fromNameOrHexOrID(e.getColorId()); + + recurrence = new Recurrence(); + + if (e.getRecurrence() != null && e.getRecurrence().size() > 0) { + recur = true; + recurrence.fromRRule(e.getRecurrence().get(0)); + } + + if (e.getSummary() != null) + summary = e.getSummary(); + + if (e.getDescription() != null) + description = e.getDescription(); + + if (e.getLocation() != null) + location = e.getLocation(); + + + startDateTime = e.getStart(); + endDateTime = e.getEnd(); + + //Here is where I need to fix the display times + GuildSettings settings = DatabaseManager.getManager().getSettings(guildId); + //TODO: Support multiple calendars + CalendarData data = DatabaseManager.getManager().getMainCalendar(guildId); + + Calendar cal = null; + try { + cal = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute(); + } catch (Exception ex) { + Logger.getLogger().exception(null, "Failed to get proper date time for event!", ex, this.getClass(), true); + } + + if (cal != null) { + + //Check if either DateTime or just Date... + if (e.getStart().getDateTime() != null) { + //DateTime + viewableStartDate = new EventDateTime().setDateTime(new DateTime(TimeUtils.applyTimeZoneOffset(e.getStart().getDateTime().getValue(), cal.getTimeZone()))); + viewableEndDate = new EventDateTime().setDateTime(new DateTime(TimeUtils.applyTimeZoneOffset(e.getEnd().getDateTime().getValue(), cal.getTimeZone()))); + } else { + //Just Date + viewableStartDate = new EventDateTime().setDate(new DateTime(TimeUtils.applyTimeZoneOffset(e.getStart().getDate().getValue(), cal.getTimeZone()))); + viewableEndDate = new EventDateTime().setDate(new DateTime(TimeUtils.applyTimeZoneOffset(e.getEnd().getDate().getValue(), cal.getTimeZone()))); + } + } else { + //Almost definitely not correct, but we need something displayed here. + viewableStartDate = e.getStart(); + viewableEndDate = e.getEnd(); + } + + eventData = DatabaseManager.getManager().getEventData(guildId, e.getId()); + + editing = false; + lastEdit = System.currentTimeMillis(); + } + + //Getters + + /** + * Gets the ID of the guild who owns this PreEvent. + * + * @return The ID of the guild who owns this PreEvent. + */ + public long getGuildId() { + return guildId; + } + + public String getEventId() { + return eventId; + } + + /** + * Gets the event summary. + * + * @return The event summary. + */ + public String getSummary() { + return summary; + } + + /** + * Gets the description. + * + * @return The description. + */ + public String getDescription() { + return description; + } + + /** + * Gets the start date and time. + * + * @return The start date and time. + */ + public EventDateTime getStartDateTime() { + return startDateTime; + } + + /** + * Gets the end date and time. + * + * @return The end date and time. + */ + public EventDateTime getEndDateTime() { + return endDateTime; + } + + /** + * Gets the viewable start date and time. + * + * @return The viewable start date and time. + */ + public EventDateTime getViewableStartDate() { + return viewableStartDate; + } + + /** + * Gets the viewable end date and time. + * + * @return The viewable end date and time. + */ + public EventDateTime getViewableEndDate() { + return viewableEndDate; + } + + /** + * Gets the timezone of the event. + * + * @return The timezone of the event. + */ + public String getTimeZone() { + return timeZone; + } + + /** + * Gets the valid Google Calendar color for this event. + * + * @return The valid color for this event. + */ + public EventColor getColor() { + return color; + } + + public String getLocation() { + return location; + } + + /** + * Gets whether or not the vent should recur. + * + * @return true if recurring, otherwise false. + */ + public boolean shouldRecur() { + return recur; + } + + /** + * Gets the recurrence rules and info for the event. + * + * @return The recurrence rules and info for the event. + */ + public Recurrence getRecurrence() { + return recurrence; + } + + public EventData getEventData() { + return eventData; + } + + public boolean isEditing() { + return editing; + } + + public IMessage getCreatorMessage() { + return creatorMessage; + } + + public long getLastEdit() { + return lastEdit; + } + + //Setters + + /** + * Sets the summary of the event. + * + * @param _summary The summary of the vent. + */ + public void setSummary(String _summary) { + summary = _summary; + } + + /** + * Sets the description of the event. + * + * @param _description The description of the event. + */ + public void setDescription(String _description) { + description = _description; + } + + /** + * Sets the start date and time of the event. + * + * @param _startDateTime The start date and time of the event. + */ + public void setStartDateTime(EventDateTime _startDateTime) { + startDateTime = _startDateTime; + } + + /** + * Sets the end date and time of the event. + * + * @param _endDateTime The end date and time of the event. + */ + public void setEndDateTime(EventDateTime _endDateTime) { + endDateTime = _endDateTime; + } + + /** + * Sets the viewable start date and time of the event. + * + * @param _viewableStart The viewable start date and time of the event. + */ + public void setViewableStartDate(EventDateTime _viewableStart) { + viewableStartDate = _viewableStart; + } + + /** + * Sets the viewable end date and time of the event. + * + * @param _viewableEnd The viewable end date and time of the event. + */ + public void setViewableEndDate(EventDateTime _viewableEnd) { + viewableEndDate = _viewableEnd; + } + + /** + * Sets the timezone of the event. + * + * @param _timeZone The timezone of the event. + */ + public void setTimeZone(String _timeZone) { + timeZone = _timeZone; + } + + /** + * Sets the valid Google Calendar color for this event. + * + * @param _color The valid color for this event. + */ + public void setColor(EventColor _color) { + color = _color; + } + + public void setLocation(String _location) { + location = _location; + } + + /** + * Sets whether or not the event should recur. + * + * @param _recur Whether or not the event should recur. + */ + public void setShouldRecur(boolean _recur) { + recur = _recur; + } + + public void setEventData(EventData _data) { + eventData = _data; + } + + public void setEditing(boolean _editing) { + editing = _editing; + } + + public void setCreatorMessage(IMessage _creatorMessage) { + creatorMessage = _creatorMessage; + } + + public void setLastEdit(long _lastEdit) { + lastEdit = _lastEdit; + } + + //Booleans/Checkers + + /** + * Whether or not the event has all required values to be created. + * + * @return true if required values set, otherwise false. + */ + public boolean hasRequiredValues() { + return startDateTime != null && endDateTime != null; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/event/Recurrence.java b/src/main/java/com/cloudcraftgaming/discal/api/object/event/Recurrence.java new file mode 100644 index 00000000..2eb7b191 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/event/Recurrence.java @@ -0,0 +1,139 @@ +package com.cloudcraftgaming.discal.api.object.event; + +import com.cloudcraftgaming.discal.api.enums.event.EventFrequency; +import com.cloudcraftgaming.discal.api.message.MessageManager; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class Recurrence { + private EventFrequency frequency; + private int interval; + private int count; + + /** + * Creates new recurrence rules and settings. + */ + public Recurrence() { + frequency = EventFrequency.DAILY; + interval = 1; + count = -1; + } + + /** + * The frequency of the event recurrence. + * + * @return The frequency of the the event recurrence. + */ + public EventFrequency getFrequency() { + return frequency; + } + + /** + * The interval at which it recurs. + * + * @return The interval at which it recurs. + */ + public int getInterval() { + return interval; + } + + /** + * The count or amount of events. + * + * @return The count of amount of events. + */ + public int getCount() { + return count; + } + + /** + * Converts settings to a Google Accepted RRule + * + * @return The RRule accepted by Google. + */ + public String toRRule() { + String rrule = "RRULE:FREQ=" + frequency.name() + ";INTERVAL=" + interval; + if (count < 1) + return rrule; //Infinite + else + return rrule + ";COUNT=" + count; + } + + /** + * Converts settings to a human readable string. + * + * @return Human readable string of the settings. + */ + public String toHumanReadable() { + String humanRead = "Frequency: " + frequency.name() + MessageManager.lineBreak + "Interval: " + interval; + if (count < 1) + return humanRead + MessageManager.lineBreak + "Amount: Infinite"; + else + return humanRead + MessageManager.lineBreak + "Amount: " + count; + } + + /** + * Sets the frequency of the event recurrence. + * + * @param _frequency The frequency of the event recurrence. + */ + public void setFrequency(EventFrequency _frequency) { + frequency = _frequency; + } + + /** + * Sets the interval of the recurrence. + * + * @param _interval The interval of the recurrence. + */ + public void setInterval(Integer _interval) { + interval = _interval; + } + + /** + * Sets the count or amount of events to create following the rules set. + * + * @param _count The amount of events to create. + */ + public void setCount(Integer _count) { + count = _count; + } + + /** + * Converts a Google RRule to the accepted settings in this object. + * + * @param rrule The RRules to convert from. + */ + public Recurrence fromRRule(String rrule) { + rrule = rrule.replaceAll("RRULE:", ""); + String[] contents = rrule.split(";"); + for (String c: contents) { + if (c.contains("FREQ=")) { + String freq = c.replaceAll("FREQ=", ""); + if (EventFrequency.isValid(freq)) + frequency = EventFrequency.fromValue(freq); + + } else if (c.contains("INTERVAL=")) { + String inter = c.replaceAll("INTERVAL=", ""); + try { + interval = Integer.valueOf(inter); + } catch (NumberFormatException e) { + //Not valid number, safe to ignore error. + interval = 1; + } + } else if (c.contains("COUNT=")) { + String con = c.replaceAll("COUNT=", ""); + try { + count = Integer.valueOf(con); + } catch (NumberFormatException e) { + //Not valid number, can ignore. + count = -1; + } + } + } + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/event/RsvpData.java b/src/main/java/com/cloudcraftgaming/discal/api/object/event/RsvpData.java new file mode 100644 index 00000000..7860b87e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/event/RsvpData.java @@ -0,0 +1,160 @@ +package com.cloudcraftgaming.discal.api.object.event; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class RsvpData { + private final long guildId; + + private String eventId; + private long eventEnd; + + private final ArrayList goingOnTime = new ArrayList<>(); + private final ArrayList goingLate = new ArrayList<>(); + private final ArrayList notGoing = new ArrayList<>(); + private final ArrayList undecided = new ArrayList<>(); + + public RsvpData(long _guildId) { + guildId = _guildId; + } + + //Getters + public long getGuildId() { + return guildId; + } + + public String getEventId() { + return eventId; + } + + public long getEventEnd() { + return eventEnd; + } + + public ArrayList getGoingOnTime() { + return goingOnTime; + } + + public ArrayList getGoingLate() { + return goingLate; + } + + public ArrayList getNotGoing() { + return notGoing; + } + + public ArrayList getUndecided() { + return undecided; + } + + public String getGoingOnTimeString() { + StringBuilder goingString = new StringBuilder(); + int i = 0; + for (String u: goingOnTime) { + if (i == 0) { + goingString = new StringBuilder(u); + } else { + goingString.append(",").append(u); + } + i++; + } + return goingString.toString(); + } + + public String getGoingLateString() { + StringBuilder goingString = new StringBuilder(); + int i = 0; + for (String u: goingLate) { + if (i == 0) { + goingString = new StringBuilder(u); + } else { + goingString.append(",").append(u); + } + i++; + } + return goingString.toString(); + } + + public String getNotGoingString() { + StringBuilder going = new StringBuilder(); + int i = 0; + for (String u: notGoing) { + if (i == 0) { + going = new StringBuilder(u); + } else { + going.append(",").append(u); + } + i++; + } + return going.toString(); + } + + public String getUndecidedString() { + StringBuilder going = new StringBuilder(); + int i = 0; + for (String u: undecided) { + if (i == 0) { + going = new StringBuilder(u); + } else { + going.append(",").append(u); + } + i++; + } + return going.toString(); + } + + //Setters + public void setEventId(String _eventId) { + eventId = _eventId; + } + + public void setEventEnd(long _eventEnd) { + eventEnd = _eventEnd; + } + + public void setGoingOnTimeFromString(String goingList) { + if (goingList != null) { + String[] subs = goingList.split(","); + Collections.addAll(goingOnTime, subs); + } + } + + public void setGoingLateFromString(String goingList) { + if (goingList != null) { + String[] subs = goingList.split(","); + Collections.addAll(goingLate, subs); + } + } + + public void setNotGoingFromString(String goingList) { + if (goingList != null) { + String[] subs = goingList.split(","); + Collections.addAll(notGoing, subs); + } + } + + public void setUndecidedFromString(String goingList) { + if (goingList != null) { + String[] subs = goingList.split(","); + Collections.addAll(undecided, subs); + } + } + + //Functions + public void removeCompletely(String userId) { + goingOnTime.remove(userId); + goingLate.remove(userId); + notGoing.remove(userId); + undecided.remove(userId); + } + + //Boolean/Checkers + public boolean shouldBeSaved() { + return goingOnTime.size() > 0 || goingLate.size() > 0 || notGoing.size() > 0 || undecided.size() > 0; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseError.java b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseError.java new file mode 100644 index 00000000..5785d811 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseError.java @@ -0,0 +1,11 @@ +package com.cloudcraftgaming.discal.api.object.json.google; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class AuthPollResponseError { + public String error; + public String error_description; +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseGrant.java b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseGrant.java new file mode 100644 index 00000000..871da110 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthPollResponseGrant.java @@ -0,0 +1,13 @@ +package com.cloudcraftgaming.discal.api.object.json.google; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class AuthPollResponseGrant { + public String access_token; + public int expires_in; + public String token_type; + public String refresh_token; +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthRefreshResponse.java b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthRefreshResponse.java new file mode 100644 index 00000000..14e4064e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/AuthRefreshResponse.java @@ -0,0 +1,12 @@ +package com.cloudcraftgaming.discal.api.object.json.google; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class AuthRefreshResponse { + public String access_token; + public int expires_in; + public String token_type; +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/CodeResponse.java b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/CodeResponse.java new file mode 100644 index 00000000..8ea383af --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/json/google/CodeResponse.java @@ -0,0 +1,14 @@ +package com.cloudcraftgaming.discal.api.object.json.google; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CodeResponse { + public String device_code; + public String user_code; + public String verification_url; + public int expires_in; + public int interval; +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/ClientData.java b/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/ClientData.java new file mode 100644 index 00000000..a89f3ead --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/ClientData.java @@ -0,0 +1,24 @@ +package com.cloudcraftgaming.discal.api.object.network.google; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class ClientData { + private final String clientId; + private final String clientSecret; + + public ClientData(String _clientId, String _clientSecret) { + clientId = _clientId; + clientSecret = _clientSecret; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/Poll.java b/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/Poll.java new file mode 100644 index 00000000..495171a0 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/network/google/Poll.java @@ -0,0 +1,66 @@ +package com.cloudcraftgaming.discal.api.object.network.google; + +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IUser; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class Poll { + private final IUser user; + private final IGuild guild; + + private int interval; + private int expires_in; + private int remainingSeconds; + private String device_code; + + public Poll(IUser _user, IGuild _guild) { + user = _user; + guild = _guild; + } + + //Getters + public IUser getUser() { + return user; + } + + public IGuild getGuild() { + return guild; + } + + public int getInterval() { + return interval; + } + + public int getExpires_in() { + return expires_in; + } + + public int getRemainingSeconds() { + return remainingSeconds; + } + + public String getDevice_code() { + return device_code; + } + + //Setters + public void setInterval(int _interval) { + interval = _interval; + } + + public void setExpires_in(int _expiresIn) { + expires_in = _expiresIn; + } + + public void setRemainingSeconds(int _remainingSeconds) { + remainingSeconds = _remainingSeconds; + } + + public void setDevice_code(String _deviceCode) { + device_code = _deviceCode; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/web/UserAPIAccount.java b/src/main/java/com/cloudcraftgaming/discal/api/object/web/UserAPIAccount.java new file mode 100644 index 00000000..38c08b42 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/web/UserAPIAccount.java @@ -0,0 +1,51 @@ +package com.cloudcraftgaming.discal.api.object.web; + +public class UserAPIAccount { + private String userId; + private String APIKey; + private boolean blocked; + private long timeIssued; + private int uses; + + //Getters + public String getUserId() { + return userId; + } + + public String getAPIKey() { + return APIKey; + } + + public boolean isBlocked() { + return blocked; + } + + public long getTimeIssued() { + return timeIssued; + } + + public int getUses() { + return uses; + } + + //Setters + public void setUserId(String _userId) { + userId = _userId; + } + + public void setAPIKey(String _apiKey) { + APIKey = _apiKey; + } + + public void setBlocked(boolean _blocked) { + blocked = _blocked; + } + + public void setTimeIssued(long _time) { + timeIssued = _time; + } + + public void setUses(int _uses) { + uses = _uses; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebCalendar.java b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebCalendar.java new file mode 100644 index 00000000..7fb12297 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebCalendar.java @@ -0,0 +1,110 @@ +package com.cloudcraftgaming.discal.api.object.web; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.model.Calendar; + +/** + * Created by Nova Fox on 1/7/18. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class WebCalendar { + private String id; + private String address; + private String link; + private String name; + private String description; + private String timezone; + + private boolean external; + + //Getters + public String getId() { + return id; + } + + public String getAddress() { + return address; + } + + public String getLink() { + return link; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getTimezone() { + return timezone; + } + + public boolean isExternal() { + return external; + } + + //Setters + public void setId(String _id) { + id = _id; + } + + public void setAddress(String _address) { + address = _address; + } + + public void setLink(String _link) { + link = _link; + } + + public void setName(String _name) { + name = _name; + } + + public void setDescription(String _desc) { + description = _desc; + } + + public void setTimezone(String _tz) { + timezone = _tz; + } + + public void setExternal(boolean _ext) { + external = _ext; + } + + //Functions + public WebCalendar fromCalendar(CalendarData cd, GuildSettings gs) { + if (cd.getCalendarAddress().equalsIgnoreCase("primary")) { + id = "primary"; + address = "primary"; + link = "N/a"; + name = "N/a"; + description = "N/a"; + timezone = "N/a"; + } else { + id = cd.getCalendarId(); + address = cd.getCalendarAddress(); + link = "https://www.discalbot.com/embed/calendar/" + gs.getGuildID(); + external = cd.isExternal(); + try { + Calendar cal = CalendarAuth.getCalendarService(gs).calendars().get(id).execute(); + name = cal.getSummary(); + description = cal.getDescription(); + timezone = cal.getTimeZone().replaceAll("/", "___"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB] Failed to get calendar!", e, this.getClass(), true); + name = "ERROR!"; + description = "ERROR"; + timezone = "ERROR"; + } + } + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebChannel.java b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebChannel.java new file mode 100644 index 00000000..3bc4ac2a --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebChannel.java @@ -0,0 +1,52 @@ +package com.cloudcraftgaming.discal.api.object.web; + +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import sx.blah.discord.handle.obj.IChannel; + +/** + * Created by Nova Fox on 1/6/18. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class WebChannel { + private long id; + private String name; + + private boolean discalChannel; + + //Getters + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isDiscalChannel() { + return discalChannel; + } + + //Setters + public void setId(long _id) { + id = _id; + } + + public void setName(String _name) { + name = _name; + } + + public void setDiscalChannel(boolean _dc) { + discalChannel = _dc; + } + + //Functions + public WebChannel fromChannel(IChannel c, GuildSettings settings) { + id = c.getLongID(); + name = c.getName(); + + discalChannel = settings.getDiscalChannel().equalsIgnoreCase(String.valueOf(id)); + + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebGuild.java b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebGuild.java new file mode 100644 index 00000000..f6a62841 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebGuild.java @@ -0,0 +1,146 @@ +package com.cloudcraftgaming.discal.api.object.web; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IRole; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Nova Fox on 12/19/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class WebGuild { + private String id; + private String name; + private String iconUrl; + + //Bot settings + private GuildSettings settings; + private String botNick; + + //User info + private boolean manageServer; + private boolean discalRole; + + //Lists and stuffs + private List roles = new ArrayList<>(); + private List channels = new ArrayList<>(); + private List announcements = new ArrayList<>(); + + private WebCalendar calendar; + + //Getters + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getIcon() { + return iconUrl; + } + + public GuildSettings getSettings() { + return settings; + } + + public String getBotNick() { + return botNick; + } + + public List getRoles() { + return roles; + } + + public List getChannels() { + return channels; + } + + public List getAnnouncements() { + return announcements; + } + + public WebCalendar getCalendar() { + return calendar; + } + + public boolean isManageServer() { + return manageServer; + } + + public boolean isDiscalRole() { + return discalRole; + } + + //Setters + public void setId(String _id) { + id = _id; + } + + public void setName(String _name) { + name = _name; + } + + public void setIcon(String _url) { + iconUrl = _url; + } + + public void setSettings(GuildSettings _settings) { + settings = _settings; + } + + public void setBotNick(String _nick) { + botNick = _nick; + } + + public void setCalendar(WebCalendar _cal) { + calendar = _cal; + } + + public void setManageServer(boolean _ms) { + manageServer = _ms; + } + + public void setDiscalRole(boolean _dr) { + discalRole = _dr; + } + + + //Functions + public WebGuild fromGuild(IGuild g) { + id = g.getStringID(); + name = g.getName(); + iconUrl = g.getIconURL(); + botNick = DisCalAPI.getAPI().getClient().getOurUser().getNicknameForGuild(g); + + settings = DatabaseManager.getManager().getSettings(g.getLongID()); + + //Handle lists and stuffs + for (IRole r: g.getRoles()) { + roles.add(new WebRole().fromRole(r, settings)); + } + + WebChannel all = new WebChannel(); + all.setId(0); + all.setName("All Channels"); + all.setDiscalChannel(settings.getDiscalChannel().equalsIgnoreCase("all")); + channels.add(all); + for (IChannel c: g.getChannels()) { + channels.add(new WebChannel().fromChannel(c, settings)); + } + announcements.addAll(DatabaseManager.getManager().getAnnouncements(g.getLongID())); + + calendar = new WebCalendar().fromCalendar(DatabaseManager.getManager().getMainCalendar(Long.valueOf(id)), settings); + + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebRole.java b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebRole.java new file mode 100644 index 00000000..30d49cf5 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/object/web/WebRole.java @@ -0,0 +1,68 @@ +package com.cloudcraftgaming.discal.api.object.web; + +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import sx.blah.discord.handle.obj.IRole; + +/** + * Created by Nova Fox on 1/6/18. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class WebRole { + private long id; + private String name; + + private boolean managed; + private boolean controlRole; + + + //Getters + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isManaged() { + return managed; + } + + public boolean isControlRole() { + return controlRole; + } + + //Setters + public void setId(long _id) { + id = _id; + } + + public void setName(String _name) { + name = _name; + } + + public void setManaged(boolean _managed) { + managed = _managed; + } + + public void setControlRole(boolean _control) { + controlRole = _control; + } + + //functions + public WebRole fromRole(IRole r, GuildSettings settings) { + id = r.getLongID(); + name = r.getName(); + + managed = r.isManaged(); + + if (r.isEveryoneRole() && settings.getControlRole().equalsIgnoreCase("everyone")) + controlRole = true; + else + controlRole = settings.getControlRole().equalsIgnoreCase(String.valueOf(id)); + + + return this; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/AnnouncementUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/AnnouncementUtils.java new file mode 100644 index 00000000..02edef25 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/AnnouncementUtils.java @@ -0,0 +1,28 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class AnnouncementUtils { + /** + * Checks if the announcement exists. + * + * @param value The announcement ID. + * @param event The event received. + * @return true if the announcement exists, else false. + */ + public static Boolean announcementExists(String value, MessageReceivedEvent event) { + for (Announcement a: DatabaseManager.getManager().getAnnouncements(event.getGuild().getLongID())) { + if (a.getAnnouncementId().toString().equals(value)) + return true; + + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/CalendarUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/CalendarUtils.java new file mode 100644 index 00000000..a12722a3 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/CalendarUtils.java @@ -0,0 +1,78 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.calendar.Calendar; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CalendarUtils { + /** + * Deletes a calendar from Google Calendar and the Db + * + * @param data The BotData of the Guild whose deleting their calendar. + * @return true if successful, else false. + */ + public static boolean deleteCalendar(CalendarData data, GuildSettings settings) { + try { + //Only delete if the calendar is stored on DisCal's account. + if (!data.getCalendarAddress().equalsIgnoreCase("primary") && !settings.useExternalCalendar()) { + Calendar service = CalendarAuth.getCalendarService(settings); + service.calendars().delete(data.getCalendarAddress()).execute(); + } + } catch (Exception e) { + //Fail silently. + Logger.getLogger().exception(null, "Failed to delete calendar", e, CalendarUtils.class, true); + return false; + } + if (settings.useExternalCalendar()) { + //Update settings. + settings.setUseExternalCalendar(false); + settings.setEncryptedAccessToken("N/a"); + settings.setEncryptedRefreshToken("N/a"); + DatabaseManager.getManager().updateSettings(settings); + } + + //Delete everything that is specific to the calendar... + DatabaseManager.getManager().deleteCalendar(data); + DatabaseManager.getManager().deleteAllEventData(data.getGuildId()); + DatabaseManager.getManager().deleteAllRSVPData(data.getGuildId()); + DatabaseManager.getManager().deleteAllAnnouncementData(data.getGuildId()); + + return true; + } + + public static boolean calendarExists(CalendarData data, GuildSettings settings) { + try { + return CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute() != null; + } catch (GoogleJsonResponseException ge) { + if (ge.getStatusCode() == 410 || ge.getStatusCode() == 404) { + //Calendar does not exist... remove from db... + settings.setUseExternalCalendar(false); + settings.setEncryptedRefreshToken("N/a"); + settings.setEncryptedAccessToken("N/a"); + DatabaseManager.getManager().updateSettings(settings); + + DatabaseManager.getManager().deleteCalendar(data); + DatabaseManager.getManager().deleteAllEventData(data.getGuildId()); + DatabaseManager.getManager().deleteAllRSVPData(data.getGuildId()); + DatabaseManager.getManager().deleteAllAnnouncementData(data.getGuildId()); + + return false; + } else { + Logger.getLogger().exception(null, "Unknown google error when checking for calendar exist", ge, CalendarUtils.class, true); + return true; + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Unknown error when checking for calendar exist", e, CalendarUtils.class, true); + return true; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/EventUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/EventUtils.java new file mode 100644 index 00000000..4c79e8f3 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/EventUtils.java @@ -0,0 +1,74 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.event.PreEvent; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class EventUtils { + /** + * Deletes an event from the calendar. + * + * @param settings Guild settings + * @param eventId The ID of the event to delete. + * @return true if successfully deleted, otherwise false. + */ + public static Boolean deleteEvent(GuildSettings settings, String eventId) { + //TODO: Support multiple calendars... + String calendarId = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()).getCalendarAddress(); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + try { + service.events().delete(calendarId, eventId).execute(); + } catch (Exception e) { + //Failed to delete event... + return false; + } + DatabaseManager.getManager().deleteAnnouncementsForEvent(settings.getGuildID(), eventId); + DatabaseManager.getManager().deleteEventData(eventId); + return true; + } catch (Exception e) { + System.out.println("Something weird happened when deleting an event!"); + Logger.getLogger().exception(null, "Failed to delete event.", e, EventUtils.class, true); + e.printStackTrace(); + } + return false; + } + + public static boolean eventExists(GuildSettings settings, String eventId) { + //TODO: Support multiple calendars... + String calendarId = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()).getCalendarAddress(); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + return service.events().get(calendarId, eventId).execute() != null; + } catch (Exception e) { + //Failed to check event, probably doesn't exist, safely ignore. + } + return false; + } + + public static PreEvent copyEvent(long guildId, Event event) { + PreEvent pe = new PreEvent(guildId); + pe.setSummary(event.getSummary()); + pe.setDescription(event.getDescription()); + pe.setLocation(event.getLocation()); + if (event.getColorId() != null) + pe.setColor(EventColor.fromNameOrHexOrID(event.getColorId())); + else + pe.setColor(EventColor.RED); + + pe.setEventData(DatabaseManager.getManager().getEventData(guildId, event.getId())); + + return pe; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/GeneralUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/GeneralUtils.java new file mode 100644 index 00000000..30bbbd1e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/GeneralUtils.java @@ -0,0 +1,76 @@ +package com.cloudcraftgaming.discal.api.utils; + +import java.util.Random; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class GeneralUtils { + /** + * Gets the contents of the message at a set offset. + * + * @param args The args of the command. + * @param offset The offset in the string. + * @return The contents of the message at a set offset. + */ + public static String getContent(String[] args, int offset) { + StringBuilder content = new StringBuilder(); + for (int i = offset; i < args.length; i++) { + content.append(args[i]).append(" "); + } + return content.toString().trim(); + } + + /** + * Trims the string front to back. + * + * @param str The String to trim. + * @return The trimmed string. + */ + public static String trim(String str) { + while (str.length() > 1 && str.charAt(0) == ' ') { + str = str.substring(1); + } + return str.trim(); + } + + /** + * Combines the arguments of a String array + * + * @param args The string array + * @param start What index to start at + * @return The combines arguments + */ + public static String combineArgs(String[] args, int start) { + if (start >= args.length) + throw new IllegalArgumentException("You can not start at an index that doesn't exit!"); + + StringBuilder res = new StringBuilder(); + for (int i = start; i < args.length; i++) { + res.append(args[i]).append(" "); + } + return res.toString().trim(); + } + + /** + * This is an overkill parser made by xaanit. You can thank him for this nightmare. + *

+ * regardless, it works, and therefore we will use it because generally speaking it seems some users do not understand that "<" and ">" are not in fact required and are just symbols CLEARLY DEFINED in our documentation. + * + * @param str The string to parse. + * @return The string, but without the user errors. + */ + public static String overkillParser(String str) { + Random random = new Random(str.length() * 2 >>> 4 & 3); + StringBuilder leftFace = new StringBuilder(); + StringBuilder rightFace = new StringBuilder(); + String alphabet = "abcdefghijklmnopqrstuvwxyz"; + for (int i = 0; i < 30; i++) { + leftFace.append(alphabet.charAt(random.nextInt(alphabet.length()))); + rightFace.append(alphabet.charAt(random.nextInt(alphabet.length()))); + } + return str.replace("<<", leftFace.toString()).replace(">>", rightFace.toString()).replace("<", "").replace(">", "").replace(leftFace.toString(), "<").replace(rightFace.toString(), ">"); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/GuildUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/GuildUtils.java new file mode 100644 index 00000000..d1753b5f --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/GuildUtils.java @@ -0,0 +1,30 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.object.web.WebGuild; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IUser; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Nova Fox on 12/17/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class GuildUtils { + public static List getGuilds(String userId) { + List guilds = new ArrayList<>(); + IUser user = DisCalAPI.getAPI().getClient().getUserByID(Long.valueOf(userId)); + for (IGuild g: DisCalAPI.getAPI().getClient().getGuilds()) { + if (g.getUserByID(Long.valueOf(userId)) != null) { + WebGuild wg = new WebGuild().fromGuild(g); + wg.setManageServer(PermissionChecker.hasManageServerRole(g, user)); + wg.setDiscalRole(PermissionChecker.hasSufficientRole(g, user)); + guilds.add(wg); + } + } + return guilds; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/ImageUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/ImageUtils.java new file mode 100644 index 00000000..61e34341 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/ImageUtils.java @@ -0,0 +1,22 @@ +package com.cloudcraftgaming.discal.api.utils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.io.IOException; +import java.net.URL; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class ImageUtils { + public static boolean validate(String url) { + try { + Image image = ImageIO.read(new URL(url)); + return image != null; + } catch (IOException e) { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/PermissionChecker.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/PermissionChecker.java new file mode 100644 index 00000000..5ce2dcca --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/PermissionChecker.java @@ -0,0 +1,144 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.logger.Logger; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.*; + +/** + * Created by Nova Fox on 1/19/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class PermissionChecker { + /** + * Checks if the user who sent the received message has the proper role to use a command. + * + * @param event The Event received to check for the user and guild. + * @return true if the user has the proper role, otherwise false. + */ + public static boolean hasSufficientRole(MessageReceivedEvent event) { + //TODO: Figure out exactly what is causing a NPE here... + try { + GuildSettings settings = DatabaseManager.getManager().getSettings(event.getGuild().getLongID()); + if (!settings.getControlRole().equalsIgnoreCase("everyone")) { + IUser sender = event.getMessage().getAuthor(); + String roleId = settings.getControlRole(); + IRole role = null; + + for (IRole r: event.getMessage().getGuild().getRoles()) { + if (r.getStringID().equals(roleId)) { + role = r; + break; + } + } + + if (role != null) { + for (IRole r: sender.getRolesForGuild(event.getMessage().getGuild())) { + if (r.getStringID().equals(role.getStringID()) || r.getPosition() > role.getPosition()) + return true; + + } + return false; + } else { + //Role not found... reset Db... + settings.setControlRole("everyone"); + DatabaseManager.getManager().updateSettings(settings); + return true; + } + } + } catch (Exception e) { + //Something broke so we will harmlessly allow access and email the dev. + Logger.getLogger().exception(event.getMessage().getAuthor(), "Failed to check for sufficient control role.", e, PermissionChecker.class, true); + return true; + } + return true; + } + + public static boolean hasSufficientRole(IGuild guild, IUser user) { + //TODO: Figure out exactly what is causing a NPE here... + try { + GuildSettings settings = DatabaseManager.getManager().getSettings(guild.getLongID()); + if (!settings.getControlRole().equalsIgnoreCase("everyone")) { + String roleId = settings.getControlRole(); + IRole role = null; + + for (IRole r: guild.getRoles()) { + if (r.getStringID().equals(roleId)) { + role = r; + break; + } + } + + if (role != null) { + for (IRole r: user.getRolesForGuild(guild)) { + if (r.getStringID().equals(role.getStringID()) || r.getPosition() > role.getPosition()) + return true; + + } + return false; + } else { + //Role not found... reset Db... + settings.setControlRole("everyone"); + DatabaseManager.getManager().updateSettings(settings); + return true; + } + } + } catch (Exception e) { + //Something broke so we will harmlessly allow access and notify the dev team + Logger.getLogger().exception(user, "Failed to check for sufficient control role.", e, PermissionChecker.class, true); + return true; + } + return true; + } + + public static boolean hasManageServerRole(MessageReceivedEvent event) { + return event.getMessage().getAuthor().getPermissionsForGuild(event.getMessage().getGuild()).contains(Permissions.MANAGE_SERVER); + } + + public static boolean hasManageServerRole(IGuild g, IUser u) { + return u.getPermissionsForGuild(g).contains(Permissions.MANAGE_SERVER); + } + + /** + * Checks if the user sent the command in a DisCal channel (if set). + * + * @param event The event received to check for the correct channel. + * @return true if in correct channel, otherwise false. + */ + public static boolean isCorrectChannel(MessageReceivedEvent event) { + try { + GuildSettings settings = DatabaseManager.getManager().getSettings(event.getGuild().getLongID()); + if (settings.getDiscalChannel().equalsIgnoreCase("all")) + return true; + + + IChannel channel = null; + for (IChannel c: event.getMessage().getGuild().getChannels()) { + if (c.getStringID().equals(settings.getDiscalChannel())) { + channel = c; + break; + } + } + + if (channel != null) + return event.getMessage().getChannel().getStringID().equals(channel.getStringID()); + + + //If we got here, the channel no longer exists, reset data and return true. + settings.setDiscalChannel("all"); + DatabaseManager.getManager().updateSettings(settings); + return true; + } catch (Exception e) { + //Catch any errors so that the bot always responds... + Logger.getLogger().exception(event.getMessage().getAuthor(), "Failed to check for discal channel.", e, PermissionChecker.class, true); + return true; + } + } + + public static boolean botHasMessageManagePerms(MessageReceivedEvent event) { + return DisCalAPI.getAPI().getClient().getOurUser().getPermissionsForGuild(event.getMessage().getGuild()).contains(Permissions.MANAGE_MESSAGES); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/api/utils/TimeUtils.java b/src/main/java/com/cloudcraftgaming/discal/api/utils/TimeUtils.java new file mode 100644 index 00000000..31a0ce8b --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/api/utils/TimeUtils.java @@ -0,0 +1,124 @@ +package com.cloudcraftgaming.discal.api.utils; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.event.PreEvent; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.util.Date; +import java.util.TimeZone; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class TimeUtils { + /** + * Checks whether or not a date has already past (IE: March 3, 1990). + * + * @param dateRaw The date to check in format (yyyy/MM/dd-HH:mm:ss). + * @param timezone The timezone of the calendar this event is for. + * @return true if the date is in the past, otherwise false. + */ + public static boolean inPast(String dateRaw, TimeZone timezone) { + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss"); + sdf.setTimeZone(timezone); + Date dateObj = sdf.parse(dateRaw); + Date now = new Date(System.currentTimeMillis()); + + return dateObj.before(now); + } catch (ParseException e) { + return true; + } + } + + private static boolean inPast(Event event) { + if (event.getStart().getDateTime() != null) + return event.getStart().getDateTime().getValue() <= System.currentTimeMillis(); + else + return event.getStart().getDate().getValue() <= System.currentTimeMillis(); + } + + public static boolean inPast(String eventId, GuildSettings settings) { + //TODO: Support multiple calendars + if (EventUtils.eventExists(settings, eventId)) { + try { + Calendar service = CalendarAuth.getCalendarService(settings); + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + Event e = service.events().get(calendarData.getCalendarId(), eventId).execute(); + return inPast(e); + } catch (Exception e) { + Logger.getLogger().exception(null, "Failed to get calendar auth", e, TimeUtils.class, true); + //Return false and allow RSVP so user is not adversely affected. + return false; + } + } + return false; + } + + /** + * Checks whether or not the end date is before the start date of the event. + * + * @param endRaw The date to check in format (yyyy/MM/dd-HH:mm:ss). + * @param timezone The timezone of the calendar this event is for. + * @param event The event that is currently being created. + * @return true if the end is before the start, otherwise false. + */ + public static boolean endBeforeStart(String endRaw, TimeZone timezone, PreEvent event) { + if (event.getStartDateTime() != null) { + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss"); + sdf.setTimeZone(timezone); + Date endDate = sdf.parse(endRaw); + Date startDate = new Date(event.getStartDateTime().getDateTime().getValue()); + + return endDate.before(startDate); + } catch (ParseException e) { + return true; + } + } + return false; + } + + /** + * Checks whether or not the start date is after the end date of the event. + * + * @param startRaw The date to check in format (yyyy/MM/dd-HH:mm:ss). + * @param timezone The timezone of the calendar this event is for. + * @param event The event that is currently being created. + * @return true of the start is after the end, otherwise false. + */ + public static boolean startAfterEnd(String startRaw, TimeZone timezone, PreEvent event) { + if (event.getEndDateTime() != null) { + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss"); + sdf.setTimeZone(timezone); + Date startDate = sdf.parse(startRaw); + Date endDate = new Date(event.getEndDateTime().getDateTime().getValue()); + + return startDate.after(endDate); + } catch (ParseException e) { + return true; + } + } + return false; + } + + public static long applyTimeZoneOffset(long epochTime, String timezone) { + long timeZoneOffset = TimeZone.getTimeZone(ZoneId.of(timezone)).getRawOffset(); + long chicagoOffset = TimeZone.getTimeZone(ZoneId.of("America/Chicago")).getRawOffset(); + + long toAdd = timeZoneOffset - chicagoOffset; + + return epochTime + toAdd; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/calendar/CalendarCreator.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/calendar/CalendarCreator.java new file mode 100644 index 00000000..34fef0d5 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/calendar/CalendarCreator.java @@ -0,0 +1,258 @@ +package com.cloudcraftgaming.discal.bot.internal.calendar.calendar; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.message.calendar.CalendarMessageFormatter; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarCreatorResponse; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.calendar.PreCalendar; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.model.AclRule; +import com.google.api.services.calendar.model.Calendar; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IMessage; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/4/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class CalendarCreator { + private static CalendarCreator instance; + + private ArrayList calendars = new ArrayList<>(); + + private CalendarCreator() { + } //Prevent initialization + + /** + * Gets the instance of the CalendarCreator. + * + * @return The instance of the CalendarCreator. + */ + public static CalendarCreator getCreator() { + if (instance == null) + instance = new CalendarCreator(); + return instance; + } + + //Functionals + + /** + * Initiates the CalendarCreator for the guild involved in the event. + * + * @param e The event received upon creation start. + * @param calendarName The name of the calendar to create. + * @return The PreCalendar object created. + */ + public PreCalendar init(MessageReceivedEvent e, String calendarName, GuildSettings settings, boolean handleCreatorMessage) { + long guildId = e.getMessage().getGuild().getLongID(); + if (!hasPreCalendar(guildId)) { + PreCalendar calendar = new PreCalendar(guildId, calendarName); + + if (handleCreatorMessage) { + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage msg = MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(calendar, settings), MessageManager.getMessage("Creator.Calendar.Create.Init", settings), e); + calendar.setCreatorMessage(msg); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + } + calendars.add(calendar); + return calendar; + } + return getPreCalendar(e.getMessage().getGuild().getLongID()); + } + + @SuppressWarnings("SameParameterValue") + public PreCalendar edit(MessageReceivedEvent event, GuildSettings settings, boolean handleCreatorMessage) { + long guildId = event.getMessage().getGuild().getLongID(); + if (!hasPreCalendar(guildId)) { + //TODO: Support multiple calendars + CalendarData data = DatabaseManager.getManager().getMainCalendar(guildId); + + try { + com.google.api.services.calendar.Calendar service = CalendarAuth.getCalendarService(settings); + + Calendar calendar = service.calendars().get(data.getCalendarAddress()).execute(); + + PreCalendar preCalendar = new PreCalendar(guildId, calendar); + preCalendar.setEditing(true); + preCalendar.setCalendarId(data.getCalendarAddress()); + + if (handleCreatorMessage) { + if (PermissionChecker.botHasMessageManagePerms(event)) { + IMessage msg = MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(preCalendar, settings), MessageManager.getMessage("Creator.Calendar.Edit.Init", settings), event); + preCalendar.setCreatorMessage(msg); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), event); + } + } + + calendars.add(preCalendar); + return preCalendar; + } catch (Exception e) { + Logger.getLogger().exception(event.getMessage().getAuthor(), "Failed to init calendar editor", e, this.getClass(), true); + return null; + } + } else { + return getPreCalendar(guildId); + } + } + + /** + * Gracefully closes down the CalendarCreator for the guild involved and DOES NOT create the calendar. + * + * @param e The event received upon termination. + * @return true if closed successfully, otherwise false. + */ + public Boolean terminate(MessageReceivedEvent e) { + if (hasPreCalendar(e.getMessage().getGuild().getLongID())) { + calendars.remove(getPreCalendar(e.getMessage().getGuild().getLongID())); + return true; + } + return false; + } + + public boolean terminate(long guildId) { + if (hasPreCalendar(guildId)) { + calendars.remove(getPreCalendar(guildId)); + return true; + } + return false; + } + + /** + * Confirms the calendar and creates it within Google Calendar. + * + * @param e The event received upon confirmation. + * @return A CalendarCreatorResponse Object with detailed info about the confirmation. + */ + public CalendarCreatorResponse confirmCalendar(MessageReceivedEvent e, GuildSettings settings) { + if (hasPreCalendar(e.getMessage().getGuild().getLongID())) { + long guildId = e.getMessage().getGuild().getLongID(); + PreCalendar preCalendar = getPreCalendar(guildId); + if (preCalendar.hasRequiredValues()) { + if (!preCalendar.isEditing()) { + Calendar calendar = new Calendar(); + calendar.setSummary(preCalendar.getSummary()); + calendar.setDescription(preCalendar.getDescription()); + calendar.setTimeZone(preCalendar.getTimezone()); + try { + com.google.api.services.calendar.Calendar service = CalendarAuth.getCalendarService(settings); + + Calendar confirmed = service.calendars().insert(calendar).execute(); + AclRule rule = new AclRule(); + AclRule.Scope scope = new AclRule.Scope(); + scope.setType("default"); + rule.setScope(scope).setRole("reader"); + service.acl().insert(confirmed.getId(), rule).execute(); + CalendarData calendarData = new CalendarData(guildId, 1); + calendarData.setCalendarId(confirmed.getId()); + calendarData.setCalendarAddress(confirmed.getId()); + DatabaseManager.getManager().updateCalendar(calendarData); + terminate(e); + CalendarCreatorResponse response = new CalendarCreatorResponse(true, confirmed); + response.setEdited(false); + response.setCreatorMessage(preCalendar.getCreatorMessage()); + return response; + } catch (Exception ex) { + Logger.getLogger().exception(e.getMessage().getAuthor(), "Failed to confirm calendar.", ex, this.getClass(), true); + CalendarCreatorResponse response = new CalendarCreatorResponse(false); + response.setEdited(false); + response.setCreatorMessage(preCalendar.getCreatorMessage()); + return response; + } + } else { + //Editing calendar... + Calendar calendar = new Calendar(); + calendar.setSummary(preCalendar.getSummary()); + calendar.setDescription(preCalendar.getDescription()); + calendar.setTimeZone(preCalendar.getTimezone()); + + try { + com.google.api.services.calendar.Calendar service = CalendarAuth.getCalendarService(settings); + + Calendar confirmed = service.calendars().update(preCalendar.getCalendarId(), calendar).execute(); + AclRule rule = new AclRule(); + AclRule.Scope scope = new AclRule.Scope(); + scope.setType("default"); + rule.setScope(scope).setRole("reader"); + service.acl().insert(confirmed.getId(), rule).execute(); + terminate(e); + CalendarCreatorResponse response = new CalendarCreatorResponse(true, confirmed); + response.setEdited(true); + response.setCreatorMessage(preCalendar.getCreatorMessage()); + return response; + } catch (Exception ex) { + Logger.getLogger().exception(e.getMessage().getAuthor(), "Failed to update calendar.", ex, this.getClass(), true); + CalendarCreatorResponse response = new CalendarCreatorResponse(false); + response.setEdited(true); + response.setCreatorMessage(preCalendar.getCreatorMessage()); + return response; + } + } + } + } + return new CalendarCreatorResponse(false); + } + + //Getters + + /** + * Gets the PreCalendar for the guild in the creator. + * + * @param guildId The ID of the guild whose PreCalendar is to be returned. + * @return The PreCalendar belonging to the guild. + */ + public PreCalendar getPreCalendar(long guildId) { + for (PreCalendar c: calendars) { + if (c.getGuildId() == guildId) { + c.setLastEdit(System.currentTimeMillis()); + return c; + } + } + return null; + } + + public IMessage getCreatorMessage(long guildId) { + if (hasPreCalendar(guildId)) + return getPreCalendar(guildId).getCreatorMessage(); + return null; + } + + public ArrayList getAllPreCalendars() { + return calendars; + } + + //Booleans/Checkers + + /** + * Checks whether or not the specified Guild has a PreCalendar in the creator. + * + * @param guildId The ID of the guild to check for. + * @return true if a PreCalendar exists, else false. + */ + public Boolean hasPreCalendar(long guildId) { + for (PreCalendar c: calendars) { + if (c.getGuildId() == guildId) + return true; + } + return false; + } + + public boolean hasCreatorMessage(long guildId) { + return hasPreCalendar(guildId) && getPreCalendar(guildId).getCreatorMessage() != null; + } + + //Setters + public void setCreatorMessage(IMessage msg) { + if (msg != null && hasPreCalendar(msg.getGuild().getLongID())) + getPreCalendar(msg.getGuild().getLongID()).setCreatorMessage(msg); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventCreator.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventCreator.java new file mode 100644 index 00000000..caa93956 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventCreator.java @@ -0,0 +1,341 @@ +package com.cloudcraftgaming.discal.bot.internal.calendar.event; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.crypto.KeyGenerator; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.event.EventCreatorResponse; +import com.cloudcraftgaming.discal.api.object.event.PreEvent; +import com.cloudcraftgaming.discal.api.utils.EventUtils; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IMessage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("Duplicates") +public class EventCreator { + private static EventCreator instance; + + private ArrayList events = new ArrayList<>(); + + private EventCreator() { + } //Prevent initialization. + + /** + * Gets the instance of the EventCreator. + * + * @return The instance of the EventCreator + */ + public static EventCreator getCreator() { + if (instance == null) + instance = new EventCreator(); + return instance; + } + + //Functionals + + /** + * Initiates the EventCreator for a specific guild. + * + * @param e The event received upon initialization. + * @return The PreEvent for the guild. + */ + public PreEvent init(MessageReceivedEvent e, GuildSettings settings, boolean handleMessage) { + if (!hasPreEvent(e.getGuild().getLongID())) { + PreEvent event = new PreEvent(e.getGuild().getLongID()); + try { + //TODO: Handle multiple calendars... + String calId = DatabaseManager.getManager().getMainCalendar(e.getGuild().getLongID()).getCalendarAddress(); + event.setTimeZone(CalendarAuth.getCalendarService(settings).calendars().get(calId).execute().getTimeZone()); + } catch (Exception exc) { + //Failed to get timezone, ignore safely. + } + if (handleMessage) { + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage message = MessageManager.sendMessage(EventMessageFormatter.getPreEventEmbed(event, settings), MessageManager.getMessage("Creator.Event.Create.Init", settings), e); + event.setCreatorMessage(message); + MessageManager.deleteMessage(e); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + } + + events.add(event); + return event; + } + return getPreEvent(e.getGuild().getLongID()); + } + + public PreEvent init(MessageReceivedEvent e, GuildSettings settings, String summary, boolean handleMessage) { + if (!hasPreEvent(e.getGuild().getLongID())) { + PreEvent event = new PreEvent(e.getGuild().getLongID()); + event.setSummary(summary); + try { + //TODO: Handle multiple calendars... + String calId = DatabaseManager.getManager().getMainCalendar(e.getGuild().getLongID()).getCalendarAddress(); + + event.setTimeZone(CalendarAuth.getCalendarService(settings).calendars().get(calId).execute().getTimeZone()); + } catch (Exception exc) { + //Failed to get timezone, ignore safely. + } + if (handleMessage) { + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage message = MessageManager.sendMessage(EventMessageFormatter.getPreEventEmbed(event, settings), MessageManager.getMessage("Creator.Event.Create.Init", settings), e); + event.setCreatorMessage(message); + MessageManager.deleteMessage(e); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + } + + events.add(event); + return event; + } + return getPreEvent(e.getGuild().getLongID()); + } + + //Copy event + public PreEvent init(MessageReceivedEvent e, String eventId, GuildSettings settings, boolean handleMessage) { + if (!hasPreEvent(e.getGuild().getLongID())) { + //TODO: Handle multiple calendars... + try { + String calId = DatabaseManager.getManager().getMainCalendar(e.getGuild().getLongID()).getCalendarAddress(); + Calendar service = CalendarAuth.getCalendarService(settings); + + Event calEvent = service.events().get(calId, eventId).execute(); + + PreEvent event = EventUtils.copyEvent(e.getGuild().getLongID(), calEvent); + + try { + event.setTimeZone(service.calendars().get(calId).execute().getTimeZone()); + } catch (IOException e1) { + //Failed to get tz, ignore safely. + } + + if (handleMessage) { + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage message = MessageManager.sendMessage(EventMessageFormatter.getPreEventEmbed(event, settings), MessageManager.getMessage("Creator.Event.Copy.Init", settings), e); + event.setCreatorMessage(message); + MessageManager.deleteMessage(e); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + } + + events.add(event); + return event; + } catch (Exception exc) { + //Something failed... + } + return null; + } + return getPreEvent(e.getGuild().getLongID()); + } + + public PreEvent edit(MessageReceivedEvent e, String eventId, GuildSettings settings, boolean handleMessage) { + long guildId = e.getGuild().getLongID(); + if (!hasPreEvent(guildId)) { + //TODO: Handle multiple calendars... + try { + String calId = DatabaseManager.getManager().getMainCalendar(guildId).getCalendarAddress(); + Calendar service = CalendarAuth.getCalendarService(settings); + + Event calEvent = service.events().get(calId, eventId).execute(); + + PreEvent event = new PreEvent(guildId, calEvent); + event.setEditing(true); + + try { + event.setTimeZone(service.calendars().get(calId).execute().getTimeZone()); + } catch (IOException ignore) { + //Failed to get tz, ignore safely. + } + + if (handleMessage) { + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage message = MessageManager.sendMessage(EventMessageFormatter.getPreEventEmbed(event, settings), MessageManager.getMessage("Creator.Event.Edit.Init", settings), e); + event.setCreatorMessage(message); + MessageManager.deleteMessage(e); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + } + + events.add(event); + return event; + } catch (Exception exc) { + //Oops + } + return null; + } + return getPreEvent(guildId); + } + + /** + * Gracefully terminates the EventCreator for a specific guild. + * + * @param e The event received upon termination. + * @return true if successful, else false. + */ + public boolean terminate(MessageReceivedEvent e) { + if (hasPreEvent(e.getGuild().getLongID())) { + events.remove(getPreEvent(e.getGuild().getLongID())); + return true; + } + return false; + } + + public boolean terminate(long guildId) { + if (hasPreEvent(guildId)) { + events.remove(getPreEvent(guildId)); + return true; + } + return false; + } + + /** + * Confirms the event in the creator for the specific guild. + * + * @param e The event received upon confirmation. + * @return The response containing detailed info about the confirmation. + */ + public EventCreatorResponse confirmEvent(MessageReceivedEvent e, GuildSettings settings) { + if (hasPreEvent(e.getGuild().getLongID())) { + long guildId = e.getGuild().getLongID(); + PreEvent preEvent = getPreEvent(guildId); + if (preEvent.hasRequiredValues()) { + Event event = new Event(); + event.setSummary(preEvent.getSummary()); + event.setDescription(preEvent.getDescription()); + event.setStart(preEvent.getStartDateTime().setTimeZone(preEvent.getTimeZone())); + event.setEnd(preEvent.getEndDateTime().setTimeZone(preEvent.getTimeZone())); + event.setVisibility("web/public"); + if (!preEvent.getColor().equals(EventColor.NONE)) + event.setColorId(String.valueOf(preEvent.getColor().getId())); + + if (preEvent.getLocation() != null && !preEvent.getLocation().equalsIgnoreCase("")) + event.setLocation(preEvent.getLocation()); + + + //Set recurrence + if (preEvent.shouldRecur()) { + String[] recurrence = new String[]{preEvent.getRecurrence().toRRule()}; + event.setRecurrence(Arrays.asList(recurrence)); + } + + //TODO handle multiple calendars... + String calendarId = DatabaseManager.getManager().getMainCalendar(guildId).getCalendarAddress(); + + if (!preEvent.isEditing()) { + event.setId(KeyGenerator.generateEventId()); + try { + Event confirmed = CalendarAuth.getCalendarService(settings).events().insert(calendarId, event).execute(); + + if (preEvent.getEventData().shouldBeSaved()) { + preEvent.getEventData().setEventId(confirmed.getId()); + preEvent.getEventData().setEventEnd(confirmed.getEnd().getDateTime().getValue()); + DatabaseManager.getManager().updateEventData(preEvent.getEventData()); + } + terminate(e); + EventCreatorResponse response = new EventCreatorResponse(true, confirmed); + response.setEdited(false); + return response; + } catch (Exception ex) { + Logger.getLogger().exception(e.getAuthor(), "Failed to create event.", ex, this.getClass(), true); + EventCreatorResponse response = new EventCreatorResponse(false); + response.setEdited(false); + return response; + } + } else { + try { + Event confirmed = CalendarAuth.getCalendarService(settings).events().update(calendarId, preEvent.getEventId(), event).execute(); + + if (preEvent.getEventData().shouldBeSaved()) { + preEvent.getEventData().setEventId(confirmed.getId()); + preEvent.getEventData().setEventEnd(confirmed.getEnd().getDateTime().getValue()); + DatabaseManager.getManager().updateEventData(preEvent.getEventData()); + } + terminate(e); + + EventCreatorResponse response = new EventCreatorResponse(true, confirmed); + response.setEdited(true); + return response; + } catch (Exception ex) { + Logger.getLogger().exception(e.getAuthor(), "Failed to update event.", ex, this.getClass(), true); + EventCreatorResponse response = new EventCreatorResponse(false); + response.setEdited(true); + return response; + } + } + } + } + return new EventCreatorResponse(false); + } + + //Getters + + /** + * gets the PreEvent for the specified guild. + * + * @param guildId The ID of the guild. + * @return The PreEvent belonging to the guild. + */ + public PreEvent getPreEvent(long guildId) { + for (PreEvent e: events) { + if (e.getGuildId() == guildId) { + e.setLastEdit(System.currentTimeMillis()); + return e; + } + } + return null; + } + + public IMessage getCreatorMessage(long guildId) { + if (hasPreEvent(guildId)) + return getPreEvent(guildId).getCreatorMessage(); + return null; + } + + public ArrayList getAllPreEvents() { + return events; + } + + //Booleans/Checkers + + /** + * Checks if the specified guild has a PreEvent in the creator. + * + * @param guildId The ID of the guild. + * @return true if a PreEvent exists, otherwise false. + */ + public boolean hasPreEvent(long guildId) { + for (PreEvent e: events) { + if (e.getGuildId() == guildId) + return true; + } + return false; + } + + public boolean hasCreatorMessage(long guildId) { + return hasPreEvent(guildId) && getPreEvent(guildId).getCreatorMessage() != null; + } + + //Setters + public void setCreatorMessage(IMessage msg) { + if (msg != null && hasPreEvent(msg.getGuild().getLongID())) + getPreEvent(msg.getGuild().getLongID()).setCreatorMessage(msg); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventMessageFormatter.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventMessageFormatter.java new file mode 100644 index 00000000..cbf2b849 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/calendar/event/EventMessageFormatter.java @@ -0,0 +1,374 @@ +package com.cloudcraftgaming.discal.bot.internal.calendar.event; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.event.EventCreatorResponse; +import com.cloudcraftgaming.discal.api.object.event.EventData; +import com.cloudcraftgaming.discal.api.object.event.PreEvent; +import com.cloudcraftgaming.discal.api.utils.ImageUtils; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; +import com.google.api.services.calendar.model.EventDateTime; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.util.EmbedBuilder; + +import javax.annotation.Nullable; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("Duplicates") +public class EventMessageFormatter { + + /** + * Gets an EmbedObject for the specified event. + * + * @param event The event involved. + * @param settings The guild's settings + * @return The EmbedObject of the event. + */ + public static EmbedObject getEventEmbed(Event event, GuildSettings settings) { + EventData ed = DatabaseManager.getManager().getEventData(settings.getGuildID(), event.getId()); + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL()); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Event.Info.Title", settings)); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + + em.appendField(MessageManager.getMessage("Embed.Event.Info.Summary", settings), summary, true); + } + if (event.getDescription() != null) { + String description = event.getDescription(); + if (description.length() > 500) { + description = description.substring(0, 500); + description = description + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Event.Info.Description", settings), description, true); + } + em.appendField(MessageManager.getMessage("Embed.Event.Info.StartDate", settings), getHumanReadableDate(event.getStart(), settings, false), true); + em.appendField(MessageManager.getMessage("Embed.Event.Info.StartTime", settings), getHumanReadableTime(event.getStart(), settings, false), true); + em.appendField(MessageManager.getMessage("Embed.Event.Info.EndDate", settings), getHumanReadableDate(event.getEnd(), settings, false), true); + em.appendField(MessageManager.getMessage("Embed.Event.Info.EndTime", settings), getHumanReadableTime(event.getEnd(), settings, false), true); + + try { + //TODO: add support for multiple calendars... + CalendarData data = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + Calendar service = CalendarAuth.getCalendarService(settings); + String tz = service.calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + em.appendField(MessageManager.getMessage("Embed.Event.Info.TimeZone", settings), tz, true); + } catch (Exception e1) { + em.appendField(MessageManager.getMessage("Embed.Event.Info.TimeZone", settings), "Error/Unknown", true); + } + if (event.getLocation() != null && !event.getLocation().equalsIgnoreCase("")) { + if (event.getLocation().length() > 300) { + String location = event.getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), event.getLocation(), true); + } + } + //TODO: Add info on recurrence here. + em.withUrl(event.getHtmlLink()); + em.withFooterText(MessageManager.getMessage("Embed.Event.Info.ID", "%id%", event.getId(), settings)); + try { + EventColor ec = EventColor.fromId(Integer.valueOf(event.getColorId())); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + } catch (Exception e) { + //Color is null, ignore and add our default. + em.withColor(56, 138, 237); + } + + return em.build(); + } + + /** + * Gets an EmbedObject for the specified event. + * + * @param event The event involved. + * @return The EmbedObject of the event. + */ + public static EmbedObject getCondensedEventEmbed(Event event, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL()); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Event.Condensed.Title", settings)); + EventData ed = DatabaseManager.getManager().getEventData(settings.getGuildID(), event.getId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) + em.withThumbnail(ed.getImageLink()); + + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Event.Condensed.Summary", settings), summary, true); + } + em.appendField(MessageManager.getMessage("Embed.Event.Condensed.Date", settings), getHumanReadableDate(event.getStart(), settings, false), true); + if (event.getLocation() != null && !event.getLocation().equalsIgnoreCase("")) { + if (event.getLocation().length() > 300) { + String location = event.getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), event.getLocation(), true); + } + } + em.appendField(MessageManager.getMessage("Embed.Event.Condensed.ID", settings), event.getId(), false); + em.withUrl(event.getHtmlLink()); + try { + EventColor ec = EventColor.fromId(Integer.valueOf(event.getColorId())); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + } catch (Exception e) { + //Color is null, ignore and add our default. + em.withColor(56, 138, 237); + } + + return em.build(); + } + + /** + * Gets an EmbedObject for the specified PreEvent. + * + * @param event The PreEvent to get an embed for. + * @return The EmbedObject of the PreEvent. + */ + public static EmbedObject getPreEventEmbed(PreEvent event, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Event.Pre.Title", settings)); + try { + if (event.getEventData() != null && event.getEventData().getImageLink() != null && ImageUtils.validate(event.getEventData().getImageLink())) { + em.withImage(event.getEventData().getImageLink()); + } + } catch (NullPointerException e) { + //TODO: find out why this is happening + Logger.getLogger().exception(null, "[Event] Failed to handle event image. Is event null?", e, EventMessageFormatter.class, true); + } + if (event.isEditing()) + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Id", settings), event.getEventId(), false); + + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Summary", settings), summary, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Summary", settings), "NOT SET", true); + } + if (event.getDescription() != null) { + String description = event.getDescription(); + if (description.length() > 500) { + description = description.substring(0, 500); + description = description + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Description", settings), description, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Description", settings), "NOT SET", true); + } + if (event.shouldRecur()) { + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Recurrence", settings), event.getRecurrence().toHumanReadable(), false); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Pre.Recurrence", settings), "N/a", true); + } + em.appendField(MessageManager.getMessage("Embed.Event.Pre.StartDate", settings), getHumanReadableDate(event.getViewableStartDate(), settings, true), true); + em.appendField(MessageManager.getMessage("Embed.Event.Pre.StartTime", settings), EventMessageFormatter.getHumanReadableTime(event.getViewableStartDate(), settings, true), true); + em.appendField(MessageManager.getMessage("Embed.Event.Pre.EndDate", settings), getHumanReadableDate(event.getViewableEndDate(), settings, true), true); + em.appendField(MessageManager.getMessage("Embed.Event.Pre.EndTime", settings), EventMessageFormatter.getHumanReadableTime(event.getViewableEndDate(), settings, true), true); + em.appendField(MessageManager.getMessage("Embed.Event.Pre.TimeZone", settings), event.getTimeZone(), true); + + if (event.getLocation() != null && !event.getLocation().equalsIgnoreCase("")) { + if (event.getLocation().length() > 300) { + String location = event.getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), event.getLocation(), true); + } + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), "N/a", true); + } + + em.withFooterText(MessageManager.getMessage("Embed.Event.Pre.Key", settings)); + EventColor ec = event.getColor(); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + + return em.build(); + } + + /** + * Gets an EmbedObject for the specified CreatorResponse. + * + * @param ecr The CreatorResponse involved. + * @return The EmbedObject for the CreatorResponse. + */ + public static EmbedObject getEventConfirmationEmbed(EventCreatorResponse ecr, GuildSettings settings) { + EventData ed = DatabaseManager.getManager().getEventData(settings.getGuildID(), ecr.getEvent().getId()); + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL()); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Event.Confirm.Title", settings)); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.ID", settings), ecr.getEvent().getId(), false); + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Date", settings), getHumanReadableDate(ecr.getEvent().getStart(), settings, false), false); + if (ecr.getEvent().getLocation() != null && !ecr.getEvent().getLocation().equalsIgnoreCase("")) { + if (ecr.getEvent().getLocation().length() > 300) { + String location = ecr.getEvent().getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), ecr.getEvent().getLocation(), true); + } + } + em.withFooterText(MessageManager.getMessage("Embed.Event.Confirm.Footer", settings)); + em.withUrl(ecr.getEvent().getHtmlLink()); + try { + EventColor ec = EventColor.fromId(Integer.valueOf(ecr.getEvent().getColorId())); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + } catch (Exception e) { + //Color is null, ignore and add our default. + em.withColor(56, 138, 237); + } + + return em.build(); + } + + /** + * Gets a formatted date. + * + * @param eventDateTime The object to get the date from. + * @return A formatted date. + */ + public static String getHumanReadableDate(@Nullable EventDateTime eventDateTime, GuildSettings settings, boolean preEvent) { + try { + if (eventDateTime == null) { + return "NOT SET"; + } else { + //Get timezone + CalendarData data = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + + String timezone; + if (!preEvent) { + timezone = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + } else { + timezone = "America/Chicago"; + } + if (eventDateTime.getDateTime() != null) { + long dateTime = eventDateTime.getDateTime().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + + return format.format(ldt); + + } else { + long dateTime = eventDateTime.getDate().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + + return format.format(ldt); + } + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Failed to format date", e, EventMessageFormatter.class, true); + return "ERROR! Code: E001"; + } + } + + /** + * Gets a formatted time. + * + * @param eventDateTime The object to get the time from. + * @return A formatted time. + */ + public static String getHumanReadableTime(@Nullable EventDateTime eventDateTime, GuildSettings settings, boolean preEvent) { + try { + if (eventDateTime == null) { + return "NOT SET"; + } else { + //Get timezone + CalendarData data = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + + String timezone; + if (!preEvent) { + timezone = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + } else { + timezone = "America/Chicago"; + } + if (eventDateTime.getDateTime() != null) { + long dateTime = eventDateTime.getDateTime().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("hh:mm:ss a"); + + return format.format(ldt); + + } else { + long dateTime = eventDateTime.getDate().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("hh:mm:ss a"); + + return format.format(ldt); + } + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Failed to format date", e, EventMessageFormatter.class, true); + return "ERROR! Code: E002"; + } + } + + public static String getHumanReadableDateTime(@Nullable EventDateTime eventDateTime, GuildSettings settings, boolean preEvent) { + try { + if (eventDateTime == null) { + return "NOT SET"; + } else { + //Get timezone + CalendarData data = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + + String timezone; + if (!preEvent) { + timezone = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + } else { + timezone = "America/Chicago"; + } + if (eventDateTime.getDateTime() != null) { + long dateTime = eventDateTime.getDateTime().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss a"); + + return format.format(ldt); + + } else { + long dateTime = eventDateTime.getDate().getValue(); + LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTime), ZoneId.of(timezone)); + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss a"); + + return format.format(ldt); + } + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Failed to format date", e, EventMessageFormatter.class, true); + return "ERROR! Code: E003"; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/consolecommand/ConsoleCommandExecutor.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/consolecommand/ConsoleCommandExecutor.java new file mode 100644 index 00000000..37a2d23c --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/consolecommand/ConsoleCommandExecutor.java @@ -0,0 +1,55 @@ +package com.cloudcraftgaming.discal.bot.internal.consolecommand; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.object.BotSettings; +import com.cloudcraftgaming.discal.bot.internal.service.ApplicationHandler; + +/** + * Created by Nova Fox on 1/2/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class ConsoleCommandExecutor { + /** + * Initiates the listener for commands via the DisCal console window. + */ + public static void init() { + if (BotSettings.ACCEPT_CLI.get().equalsIgnoreCase("true")) { + while (true) { + System.out.println("Enter a command below: "); + String input = System.console().readLine(); + boolean cmdValid = false; + if (input != null && !input.isEmpty()) { + + //Important commands first. + if (input.equalsIgnoreCase("exit")) { + ApplicationHandler.exitApplication(); + return; + } + if (input.equalsIgnoreCase("restart")) { + ApplicationHandler.restartApplication(null); + return; + } + if (input.equalsIgnoreCase("?")) { + cmdValid = true; + System.out.println("Valid console commands: "); + System.out.println("exit"); + System.out.println("restart"); + System.out.println("serverCount"); + System.out.println("silence true/false"); + System.out.println(); + } + if (input.startsWith("serverCount")) { + cmdValid = true; + System.out.println("Server count: " + DisCalAPI.getAPI().getClient().getGuilds().size()); + } + + if (!cmdValid) { + System.out.println("Command not found! Use ? to list all commands."); + System.out.println(); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordbots/UpdateDisBotData.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordbots/UpdateDisBotData.java new file mode 100644 index 00000000..3d796401 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordbots/UpdateDisBotData.java @@ -0,0 +1,43 @@ +package com.cloudcraftgaming.discal.bot.internal.network.discordbots; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.object.BotSettings; +import org.discordbots.api.client.DiscordBotListAPI; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * Created by Nova Fox on 2/13/18. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class UpdateDisBotData { + private static DiscordBotListAPI api; + private static Timer timer; + + public static void init() { + if (BotSettings.UPDATE_SITES.get().equalsIgnoreCase("true")) { + + api = new DiscordBotListAPI.Builder().token(BotSettings.DBO_TOKEN.get()).build(); + + timer = new Timer(true); + timer.schedule(new TimerTask() { + @Override + public void run() { + updateStats(); + } + }, 60 * 60 * 1000); + } + } + + public static void shutdown() { + if (timer != null) + timer.cancel(); + } + + private static void updateStats() { + if (api != null) + api.setStats(BotSettings.ID.get(), DisCalAPI.getAPI().getClient().getGuilds().size()); + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordpw/UpdateDisPwData.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordpw/UpdateDisPwData.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordpw/UpdateDisPwData.java rename to src/main/java/com/cloudcraftgaming/discal/bot/internal/network/discordpw/UpdateDisPwData.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/ApplicationHandler.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/ApplicationHandler.java new file mode 100644 index 00000000..ccd2105a --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/ApplicationHandler.java @@ -0,0 +1,113 @@ +package com.cloudcraftgaming.discal.bot.internal.service; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.bot.internal.network.discordbots.UpdateDisBotData; +import com.cloudcraftgaming.discal.bot.internal.network.discordpw.UpdateDisPwData; +import com.cloudcraftgaming.discal.bot.module.announcement.AnnouncementThreader; +import com.cloudcraftgaming.discal.logger.Logger; +import com.cloudcraftgaming.discal.web.handler.DiscordAccountHandler; +import sx.blah.discord.util.DiscordException; + +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.List; + +/** + * Created by Nova Fox on 6/21/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class ApplicationHandler { + + /** + * Sun property pointing the main class and its arguments. + * Might not be defined on non Hotspot VM implementations. + */ + private static final String SUN_JAVA_COMMAND = "sun.java.command"; + + /** + * Restart the current Java application + *

+ * Code provided by: https://dzone.com/articles/programmatically-restart-java + * + * @param runBeforeRestart some custom code to be run before restarting + */ + public static void restartApplication(Runnable runBeforeRestart) { + try { + // java binary + String java = System.getProperty("java.home") + "/bin/java"; + // vm arguments + List vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments(); + StringBuilder vmArgsOneLine = new StringBuilder(); + for (String arg: vmArguments) { + // if it's the agent argument : we ignore it otherwise the + // address of the old application and the new one will be in conflict + if (!arg.contains("-agentlib")) { + vmArgsOneLine.append(arg); + vmArgsOneLine.append(" "); + } + } + // init the command to execute, add the vm args + final StringBuffer cmd = new StringBuffer("\"" + java + "\" " + vmArgsOneLine); + + // program main and program arguments + String[] mainCommand = System.getProperty(SUN_JAVA_COMMAND).split(" "); + // program main is a jar + if (mainCommand[0].endsWith(".jar")) { + // if it's a jar, add -jar mainJar + cmd.append("-jar ").append(new File(mainCommand[0]).getPath()); + } else { + // else it's a .class, add the classpath and mainClass + cmd.append("-cp \"").append(System.getProperty("java.class.path")).append("\" ").append(mainCommand[0]); + } + // finally add program arguments + for (int i = 1; i < mainCommand.length; i++) { + cmd.append(" "); + cmd.append(mainCommand[i]); + } + // execute the command in a shutdown hook, to be sure that all the + // resources have been disposed before restarting the application + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + Runtime.getRuntime().exec(cmd.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + })); + // execute some custom code before restarting + if (runBeforeRestart != null) { + runBeforeRestart.run(); + } + + //MY CODE: Gracefully exit processes: + System.out.println("Restarting Discord bot!"); + + exitApplication(); + } catch (Exception e) { + // something went wrong + Logger.getLogger().exception(null, "Failed to restart bot!", e, ApplicationHandler.class, true); + } + } + + /** + * Exits the application gracefully and shuts down the bot gracefully. + */ + public static void exitApplication() { + System.out.println("Shutting down Discord bot!"); + try { + DisCalAPI.getAPI().getClient().logout(); + } catch (DiscordException | NoSuchMethodError e) { + //No need to print, exiting anyway. + e.printStackTrace(); + } + UpdateDisBotData.shutdown(); + UpdateDisPwData.shutdown(); + AnnouncementThreader.getThreader().shutdown(); + TimeManager.getManager().shutdown(); + DiscordAccountHandler.getHandler().shutdown(); + DatabaseManager.getManager().disconnectFromMySQL(); + System.exit(0); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/CreatorCleaner.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/CreatorCleaner.java new file mode 100644 index 00000000..c99c17a3 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/CreatorCleaner.java @@ -0,0 +1,74 @@ +package com.cloudcraftgaming.discal.bot.internal.service; + +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import com.cloudcraftgaming.discal.api.object.calendar.PreCalendar; +import com.cloudcraftgaming.discal.api.object.event.PreEvent; +import com.cloudcraftgaming.discal.bot.internal.calendar.calendar.CalendarCreator; +import com.cloudcraftgaming.discal.bot.internal.calendar.event.EventCreator; +import com.cloudcraftgaming.discal.bot.module.announcement.AnnouncementCreator; +import com.cloudcraftgaming.discal.logger.Logger; + +import java.util.ArrayList; +import java.util.TimerTask; + +/** + * Created by Nova Fox on 11/2/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class CreatorCleaner extends TimerTask { + + @Override + public void run() { + try { + long target = 60 * 1000 * 60; //60 minutes + + ArrayList cals = new ArrayList<>(); + ArrayList events = new ArrayList<>(); + ArrayList ans = new ArrayList<>(); + + //Run through calendar creator + for (PreCalendar cal: CalendarCreator.getCreator().getAllPreCalendars()) { + long difference = System.currentTimeMillis() - cal.getLastEdit(); + + if (difference <= target) { + //Last edited 60+ minutes ago, delete from creator and free up RAM. + cals.add(cal); + } + } + + //Run through event creator + for (PreEvent event: EventCreator.getCreator().getAllPreEvents()) { + long difference = System.currentTimeMillis() - event.getLastEdit(); + + if (difference <= target) { + //Last edited 60+ minutes ago, delete from creator and free up RAM. + events.add(event); + } + } + + //Run through announcement creator + for (Announcement an: AnnouncementCreator.getCreator().getAllAnnouncements()) { + long difference = System.currentTimeMillis() - an.getLastEdit(); + + if (difference <= target) { + //Last edited 60+ minutes ago, delete from creator and free up RAM. + ans.add(an); + } + } + + //Okay, actually go through it all and delete + for (PreCalendar c: cals) { + CalendarCreator.getCreator().terminate(c.getGuildId()); + } + for (PreEvent e: events) { + EventCreator.getCreator().terminate(e.getGuildId()); + } + for (Announcement a: ans) { + AnnouncementCreator.getCreator().terminate(a.getGuildId()); + } + } catch (Exception e) { + Logger.getLogger().exception(null, "Error in CreatorCleaner", e, this.getClass(), true); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/TimeManager.java b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/TimeManager.java new file mode 100644 index 00000000..b6ee756b --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/internal/service/TimeManager.java @@ -0,0 +1,58 @@ +package com.cloudcraftgaming.discal.bot.internal.service; + +import com.cloudcraftgaming.discal.bot.module.misc.StatusChanger; + +import java.util.ArrayList; +import java.util.Timer; + +/** + * Created by Nova Fox on 3/5/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class TimeManager { + private static TimeManager instance; + + private final ArrayList timers = new ArrayList<>(); + + private TimeManager() { + } //Prevent initialization + + /** + * Gets the instance of the TimeManager that is loaded. + * + * @return The instance of the TimeManager. + */ + public static TimeManager getManager() { + if (instance == null) + instance = new TimeManager(); + + return instance; + } + + /** + * Initializes the TimeManager and schedules the appropriate Timers. + */ + public void init() { + Timer timer = new Timer(true); + timer.schedule(new StatusChanger(), 10 * 1000, 10 * 1000); + timers.add(timer); + + //Timer at = new Timer(true); + //at.schedule(new AnnouncementTask(), 5 * 1000 * 60, 5 * 1000 * 60); + //timers.add(at); + + Timer cc = new Timer(true); + cc.schedule(new CreatorCleaner(), 60 * 1000 * 60, 60 * 1000 * 60); + timers.add(cc); + } + + /** + * Gracefully shuts down the TimeManager and exits all timer threads preventing errors. + */ + void shutdown() { + for (Timer t: timers) { + t.cancel(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/listeners/ReadyEventListener.java b/src/main/java/com/cloudcraftgaming/discal/bot/listeners/ReadyEventListener.java new file mode 100644 index 00000000..7dea8bad --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/listeners/ReadyEventListener.java @@ -0,0 +1,46 @@ +package com.cloudcraftgaming.discal.bot.listeners; + +import com.cloudcraftgaming.discal.Main; +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.bot.internal.network.discordbots.UpdateDisBotData; +import com.cloudcraftgaming.discal.bot.internal.network.discordpw.UpdateDisPwData; +import com.cloudcraftgaming.discal.bot.internal.service.TimeManager; +import com.cloudcraftgaming.discal.bot.module.announcement.AnnouncementThreader; +import com.cloudcraftgaming.discal.logger.Logger; +import sx.blah.discord.api.events.EventSubscriber; +import sx.blah.discord.handle.impl.events.ReadyEvent; + +/** + * Created by Nova Fox on 1/2/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("unused") +public class ReadyEventListener { + @EventSubscriber + public void onReadyEvent(ReadyEvent event) { + Logger.getLogger().debug("Ready!"); + try { + TimeManager.getManager().init(); + + //Lets test the new announcement multi-threader... + AnnouncementThreader.getThreader().init(); + + UpdateDisBotData.init(); + UpdateDisPwData.init(); + + MessageManager.reloadLangs(); + + try { + DisCalAPI.getAPI().iconUrl = DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL(); + } catch (Exception e) { + Logger.getLogger().exception(null, "Fuck a duck.", e, Main.class, true); + } + + Logger.getLogger().debug("[ReadyEvent] Connection success!"); + } catch (Exception e) { + Logger.getLogger().exception(null, "BAD!!!", e, this.getClass(), false); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementCreator.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementCreator.java new file mode 100644 index 00000000..486c42f1 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementCreator.java @@ -0,0 +1,202 @@ +package com.cloudcraftgaming.discal.bot.module.announcement; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import com.cloudcraftgaming.discal.api.object.announcement.AnnouncementCreatorResponse; +import com.cloudcraftgaming.discal.api.utils.AnnouncementUtils; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IMessage; + +import java.util.ArrayList; +import java.util.UUID; + +/** + * Created by Nova Fox on 3/4/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class AnnouncementCreator { + private static AnnouncementCreator instance; + + private ArrayList announcements = new ArrayList<>(); + + private AnnouncementCreator() { + } //Prevent initialization + + /** + * Gets the instance of the AnnouncementCreator. + * + * @return The instance of the AnnouncementCreator. + */ + public static AnnouncementCreator getCreator() { + if (instance == null) { + instance = new AnnouncementCreator(); + } + return instance; + } + + //Functionals + + /** + * Initiates the creator for the guild involved. + * + * @param e The event received upon init. + * @return A new Announcement. + */ + public Announcement init(MessageReceivedEvent e, GuildSettings settings) { + if (!hasAnnouncement(e.getGuild().getLongID())) { + Announcement a = new Announcement(e.getGuild().getLongID()); + a.setAnnouncementChannelId(e.getChannel().getStringID()); + + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage msg = MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Create.Init", settings), e); + a.setCreatorMessage(msg); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + + announcements.add(a); + return a; + } + return getAnnouncement(e.getGuild().getLongID()); + } + + public Announcement init(MessageReceivedEvent e, String announcementId, GuildSettings settings) { + if (!hasAnnouncement(e.getGuild().getLongID()) && AnnouncementUtils.announcementExists(announcementId, e)) { + Announcement toCopy = DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementId), e.getGuild().getLongID()); + + //Copy + Announcement a = new Announcement(toCopy); + + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage msg = MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Copy.Success", settings), e); + a.setCreatorMessage(msg); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + + announcements.add(a); + return a; + } + return getAnnouncement(e.getGuild().getLongID()); + } + + public Announcement edit(MessageReceivedEvent e, String announcementId, GuildSettings settings) { + if (!hasAnnouncement(e.getGuild().getLongID()) && AnnouncementUtils.announcementExists(announcementId, e)) { + Announcement edit = DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementId), e.getGuild().getLongID()); + + //Copy + Announcement a = new Announcement(edit, true); + a.setEditing(true); + + if (PermissionChecker.botHasMessageManagePerms(e)) { + IMessage msg = MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Edit.Init", settings), e); + a.setCreatorMessage(msg); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Notif.MANAGE_MESSAGES", settings), e); + } + + announcements.add(a); + return a; + } + return getAnnouncement(e.getGuild().getLongID()); + } + + /** + * Terminates the creator gracefully. + * + * @param e The event received upon termination. + * @return Whether or not the Creator was successfully terminated. + */ + public boolean terminate(MessageReceivedEvent e) { + if (hasAnnouncement(e.getGuild().getLongID())) { + announcements.remove(getAnnouncement(e.getGuild().getLongID())); + return true; + } + return false; + } + + public boolean terminate(long guildId) { + if (hasAnnouncement(guildId)) { + announcements.remove(getAnnouncement(guildId)); + return true; + } + return false; + } + + /** + * Confirms the announcement and enters it into the Database. + * + * @param e The event received upon confirmation. + * @return An AnnouncementCreatorResponse with detailed information. + */ + public AnnouncementCreatorResponse confirmAnnouncement(MessageReceivedEvent e) { + if (hasAnnouncement(e.getGuild().getLongID())) { + long guildId = e.getGuild().getLongID(); + Announcement a = getAnnouncement(guildId); + if (a.hasRequiredValues()) { + DatabaseManager.getManager().updateAnnouncement(a); + terminate(e); + return new AnnouncementCreatorResponse(true, a); + } + } + return new AnnouncementCreatorResponse(false); + } + + //Getters + + /** + * Gets the Announcement in the creator for the guild. + * + * @param guildId The ID of the guild + * @return The Announcement in the creator for the guild. + */ + public Announcement getAnnouncement(long guildId) { + for (Announcement a: announcements) { + if (a.getGuildId() == guildId) { + a.setLastEdit(System.currentTimeMillis()); + return a; + } + } + return null; + } + + public IMessage getCreatorMessage(long guildId) { + if (hasAnnouncement(guildId)) + return getAnnouncement(guildId).getCreatorMessage(); + return null; + } + + public ArrayList getAllAnnouncements() { + return announcements; + } + + //Setters + public void setCreatorMessage(IMessage message) { + if (message != null && hasCreatorMessage(message.getGuild().getLongID())) + getAnnouncement(message.getGuild().getLongID()).setCreatorMessage(message); + } + + //Booleans/Checkers + + /** + * Whether or not the Guild has an announcement in the creator. + * + * @param guildId The ID of the guild. + * @return true if active, else false. + */ + public boolean hasAnnouncement(long guildId) { + for (Announcement a: announcements) { + if (a.getGuildId() == guildId) + return true; + } + return false; + } + + public boolean hasCreatorMessage(long guildId) { + return hasAnnouncement(guildId) && getAnnouncement(guildId).getCreatorMessage() != null; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementMessageFormatter.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementMessageFormatter.java new file mode 100644 index 00000000..a1a11dc3 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementMessageFormatter.java @@ -0,0 +1,438 @@ +package com.cloudcraftgaming.discal.bot.module.announcement; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.announcement.AnnouncementType; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.message.MessageManager; +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.utils.ImageUtils; +import com.cloudcraftgaming.discal.bot.internal.calendar.event.EventMessageFormatter; +import com.cloudcraftgaming.discal.bot.utils.ChannelUtils; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IRole; +import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.EmbedBuilder; + +/** + * Created by Nova Fox on 3/4/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("Duplicates") +public class AnnouncementMessageFormatter { + + /** + * Gets the EmbedObject for an Announcement. + * + * @param a The Announcement to embed. + * @return The EmbedObject for the Announcement. + */ + public static EmbedObject getFormatAnnouncementEmbed(Announcement a, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Announcement.Info.Title", settings)); + try { + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.ID", settings), a.getAnnouncementId().toString(), true); + } catch (NullPointerException e) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.ID", settings), "ID IS NULL???", true); + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Type", settings), a.getAnnouncementType().name(), true); + if (a.getAnnouncementType().equals(AnnouncementType.SPECIFIC)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.EventID", settings), a.getEventId(), true); + EventData ed = DatabaseManager.getManager().getEventData(a.getGuildId(), a.getEventId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + } else if (a.getAnnouncementType().equals(AnnouncementType.COLOR)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Color", settings), a.getEventColor().name(), true); + } else if (a.getAnnouncementType().equals(AnnouncementType.RECUR)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.RecurID", settings), a.getEventId(), true); + EventData ed = DatabaseManager.getManager().getEventData(a.getGuildId(), a.getEventId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Hours", settings), String.valueOf(a.getHoursBefore()), true); + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Minutes", settings), String.valueOf(a.getMinutesBefore()), true); + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Channel", settings), ChannelUtils.getChannelNameFromNameOrId(a.getAnnouncementChannelId(), a.getGuildId()), true); + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Info", settings), a.getInfo(), false); + if (a.getAnnouncementType().equals(AnnouncementType.COLOR)) { + EventColor c = a.getEventColor(); + em.withColor(c.getR(), c.getG(), c.getB()); + } else { + em.withColor(56, 138, 237); + } + + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Enabled", settings), a.isEnabled() + "", true); + + return em.build(); + } + + /** + * Gets the EmbedObject for a Condensed Announcement. + * + * @param a The Announcement to embed. + * @return The EmbedObject for a Condensed Announcement. + */ + public static EmbedObject getCondensedAnnouncementEmbed(Announcement a, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Announcement.Condensed.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.ID", settings), a.getAnnouncementId().toString(), false); + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.Time", settings), condensedTime(a), false); + + if (a.getAnnouncementType().equals(AnnouncementType.SPECIFIC)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.EventID", settings), a.getEventId(), false); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + //TODO: Handle multiple calendars... + + CalendarData data = DatabaseManager.getManager().getMainCalendar(a.getGuildId()); + Event event = service.events().get(data.getCalendarAddress(), a.getEventId()).execute(); + EventData ed = DatabaseManager.getManager().getEventData(settings.getGuildID(), event.getId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withThumbnail(ed.getImageLink()); + } + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.Summary", settings), summary, true); + } + } catch (Exception e) { + //Failed to get from google cal. + Logger.getLogger().exception(null, "Failed to get event for announcement.", e, AnnouncementMessageFormatter.class, true); + } + } else if (a.getAnnouncementType().equals(AnnouncementType.COLOR)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.Color", settings), a.getEventColor().name(), true); + } else if (a.getAnnouncementType().equals(AnnouncementType.RECUR)) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Condensed.RecurID", settings), a.getEventId(), true); + } + em.withFooterText(MessageManager.getMessage("Embed.Announcement.Condensed.Type", "%type%", a.getAnnouncementType().name(), settings)); + + if (a.getAnnouncementType().equals(AnnouncementType.COLOR)) { + EventColor c = a.getEventColor(); + em.withColor(c.getR(), c.getG(), c.getB()); + } else { + em.withColor(56, 138, 237); + } + + em.appendField(MessageManager.getMessage("Embed.Announcement.Info.Enabled", settings), a.isEnabled() + "", true); + + return em.build(); + } + + /** + * Sends an embed with the announcement info in a proper format. + * + * @param announcement The announcement to send info about. + * @param event the calendar event the announcement is for. + * @param data The BotData belonging to the guild. + */ + static void sendAnnouncementMessage(Announcement announcement, Event event, CalendarData data, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(announcement.getGuildId()); + + assert guild != null; + + //Set all of the stuff for embeds regardless of announcement settings + if (settings.isBranded()) + em.withAuthorName(guild.getName()); + else + em.withAuthorName("DisCal"); + + em.withTitle(MessageManager.getMessage("Embed.Announcement.Announce.Title", settings)); + EventData ed = DatabaseManager.getManager().getEventData(announcement.getGuildId(), event.getId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + + em.withUrl(event.getHtmlLink()); + + try { + EventColor ec = EventColor.fromNameOrHexOrID(event.getColorId()); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + } catch (Exception e) { + //I dunno, color probably null. + em.withColor(56, 138, 237); + } + + if (!settings.usingSimpleAnnouncements()) { + em.withFooterText(MessageManager.getMessage("Embed.Announcement.Announce.ID", "%id%", announcement.getAnnouncementId().toString(), settings)); + } + + if (announcement.isInfoOnly() && announcement.getInfo() != null && !announcement.getInfo().equalsIgnoreCase("none")) { + //Only send info... + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Info", settings), announcement.getInfo(), false); + } else { + //Requires all announcement data + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Summary", settings), summary, true); + } + if (event.getDescription() != null) { + String description = event.getDescription(); + if (description.length() > 250) { + description = description.substring(0, 250); + description = description + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Description", settings), description, true); + } + if (!settings.usingSimpleAnnouncements()) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Date", settings), EventMessageFormatter.getHumanReadableDate(event.getStart(), settings, false), true); + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Time", settings), EventMessageFormatter.getHumanReadableTime(event.getStart(), settings, false), true); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + String tz = service.calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.TimeZone", settings), tz, true); + } catch (Exception e1) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.TimeZone", settings), "Unknown *Error Occurred", true); + } + } else { + String start = EventMessageFormatter.getHumanReadableDate(event.getStart(), settings, false) + " at " + EventMessageFormatter.getHumanReadableTime(event.getStart(), settings, false); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + String tz = service.calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + start = start + " " + tz; + } catch (Exception e1) { + start = start + " (TZ UNKNOWN/ERROR)"; + } + + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Start", settings), start, false); + } + + if (event.getLocation() != null && !event.getLocation().equalsIgnoreCase("")) { + if (event.getLocation().length() > 300) { + String location = event.getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), event.getLocation(), true); + } + } + + if (!settings.usingSimpleAnnouncements()) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.EventID", settings), event.getId(), false); + } + if (!announcement.getInfo().equalsIgnoreCase("None") && !announcement.getInfo().equalsIgnoreCase("")) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Info", settings), announcement.getInfo(), false); + } + } + + + IChannel channel = null; + + try { + channel = guild.getChannelByID(Long.valueOf(announcement.getAnnouncementChannelId())); + } catch (Exception e) { + Logger.getLogger().exception(null, "An error occurred when looking for announcement channel! | Announcement: " + announcement.getAnnouncementId() + " | TYPE: " + announcement.getAnnouncementType() + " | Guild: " + announcement.getGuildId(), e, AnnouncementMessageFormatter.class, true); + } + + if (channel == null) { + //Channel does not exist or could not be found, automatically delete announcement to prevent issues. + DatabaseManager.getManager().deleteAnnouncement(announcement.getAnnouncementId().toString()); + return; + } + + MessageManager.sendMessageAsync(em.build(), getSubscriberMentions(announcement, guild), channel); + } + + static void sendAnnouncementDM(Announcement announcement, Event event, IUser user, CalendarData data, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.Announcement.Announce.Title", settings)); + EventData ed = DatabaseManager.getManager().getEventData(announcement.getGuildId(), event.getId()); + if (ed.getImageLink() != null && ImageUtils.validate(ed.getImageLink())) { + em.withImage(ed.getImageLink()); + } + if (event.getSummary() != null) { + String summary = event.getSummary(); + if (summary.length() > 250) { + summary = summary.substring(0, 250); + summary = summary + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Summary", settings), summary, true); + } + if (event.getDescription() != null) { + String description = event.getDescription(); + if (description.length() > 250) { + description = description.substring(0, 250); + description = description + " (continues on Google Calendar View)"; + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Description", settings), description, true); + } + if (!settings.usingSimpleAnnouncements()) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Date", settings), EventMessageFormatter.getHumanReadableDate(event.getStart(), settings, false), true); + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Time", settings), EventMessageFormatter.getHumanReadableTime(event.getStart(), settings, false), true); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + String tz = service.calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.TimeZone", settings), tz, true); + } catch (Exception e1) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.TimeZone", settings), "Unknown *Error Occurred", true); + } + } else { + String start = EventMessageFormatter.getHumanReadableDate(event.getStart(), settings, false) + " at " + EventMessageFormatter.getHumanReadableTime(event.getStart(), settings, false); + try { + Calendar service = CalendarAuth.getCalendarService(settings); + String tz = service.calendars().get(data.getCalendarAddress()).execute().getTimeZone(); + start = start + " " + tz; + } catch (Exception e1) { + start = start + " (TZ UNKNOWN/ERROR)"; + } + + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Start", settings), start, false); + } + + if (event.getLocation() != null && !event.getLocation().equalsIgnoreCase("")) { + if (event.getLocation().length() > 300) { + String location = event.getLocation().substring(0, 300).trim() + "... (cont. on Google Cal)"; + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), location, true); + } else { + em.appendField(MessageManager.getMessage("Embed.Event.Confirm.Location", settings), event.getLocation(), true); + } + } + + if (!settings.usingSimpleAnnouncements()) { + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.EventID", settings), event.getId(), false); + } + em.appendField(MessageManager.getMessage("Embed.Announcement.Announce.Info", settings), announcement.getInfo(), false); + em.withUrl(event.getHtmlLink()); + if (!settings.usingSimpleAnnouncements()) { + em.withFooterText(MessageManager.getMessage("Embed.Announcement.Announce.ID", "%id%", announcement.getAnnouncementId().toString(), settings)); + } + try { + EventColor ec = EventColor.fromNameOrHexOrID(event.getColorId()); + em.withColor(ec.getR(), ec.getG(), ec.getB()); + } catch (Exception e) { + //I dunno, color probably null. + em.withColor(56, 138, 237); + } + + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(announcement.getGuildId()); + + String msg = MessageManager.getMessage("Embed.Announcement.Announce.Dm.Message", "%guild%", guild.getName(), settings); + + MessageManager.sendDirectMessage(msg, em.build(), user); + } + + /** + * Gets the formatted time from an Announcement. + * + * @param a The Announcement. + * @return The formatted time from an Announcement. + */ + private static String condensedTime(Announcement a) { + return a.getHoursBefore() + "H" + a.getMinutesBefore() + "m"; + } + + public static String getSubscriberNames(Announcement a) { + //Loop and get subs without mentions... + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(a.getGuildId()); + + StringBuilder userMentions = new StringBuilder(); + for (String userId: a.getSubscriberUserIds()) { + try { + IUser user = guild.getUserByID(Long.valueOf(userId)); + if (user != null) + userMentions.append(user.getName()).append(" "); + } catch (Exception e) { + //User does not exist, safely ignore. + } + } + + StringBuilder roleMentions = new StringBuilder(); + boolean mentionEveryone = false; + boolean mentionHere = false; + for (String roleId: a.getSubscriberRoleIds()) { + if (roleId.equalsIgnoreCase("everyone")) { + mentionEveryone = true; + } else if (roleId.equalsIgnoreCase("here")) { + mentionHere = true; + } else { + try { + IRole role = guild.getRoleByID(Long.valueOf(roleId)); + if (role != null) + roleMentions.append(role.getName()).append(" "); + } catch (Exception ignore) { + //Role does not exist, safely ignore. + } + } + } + + String message = "Subscribers: " + userMentions + " " + roleMentions; + if (mentionEveryone) + message = message + " " + guild.getEveryoneRole().getName(); + + if (mentionHere) + message = message + " here"; + + return message; + } + + private static String getSubscriberMentions(Announcement a, IGuild guild) { + StringBuilder userMentions = new StringBuilder(); + for (String userId: a.getSubscriberUserIds()) { + try { + IUser user = guild.getUserByID(Long.valueOf(userId)); + if (user != null) + userMentions.append(user.mention(true)).append(" "); + + } catch (Exception e) { + //User does not exist, safely ignore. + } + } + + StringBuilder roleMentions = new StringBuilder(); + boolean mentionEveryone = false; + boolean mentionHere = false; + for (String roleId: a.getSubscriberRoleIds()) { + if (roleId.equalsIgnoreCase("everyone")) { + mentionEveryone = true; + } else if (roleId.equalsIgnoreCase("here")) { + mentionHere = true; + } else { + try { + IRole role = guild.getRoleByID(Long.valueOf(roleId)); + if (role != null) + roleMentions.append(role.mention()).append(" "); + } catch (Exception e) { + //Role does not exist, safely ignore. + } + } + } + if (!mentionEveryone && !mentionHere && userMentions.toString().equals("") && roleMentions.toString().equals("")) + return ""; + + + String message = "Subscribers: " + userMentions + " " + roleMentions; + if (mentionEveryone) + message = message + " " + guild.getEveryoneRole().mention(); + + if (mentionHere) + message = message + " @here"; + + return message; + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThread.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThread.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThread.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThread.java diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThreader.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThreader.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThreader.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/announcement/AnnouncementThreader.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AddCalendarCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AddCalendarCommand.java new file mode 100644 index 00000000..c8d52e38 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AddCalendarCommand.java @@ -0,0 +1,133 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +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.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.CalendarListEntry; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Nova Fox on 6/29/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class AddCalendarCommand implements ICommand { + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "addCalendar"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + ArrayList aliases = new ArrayList<>(); + aliases.add("addcal"); + + return aliases; + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("addCalendar"); + info.setDescription("Starts the process of adding an external calendar"); + info.setExample("!addCalendar (calendar ID)"); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (settings.isDevGuild() || settings.isPatronGuild()) { + if (PermissionChecker.hasManageServerRole(event)) { + if (args.length == 0) { + if (DatabaseManager.getManager().getMainCalendar(settings.getGuildID()).getCalendarAddress().equalsIgnoreCase("primary")) { + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Start", settings), event); + Authorization.getAuth().requestCode(event, settings); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } else if (args.length == 1) { + //Check if arg is calendar ID that is supported, if so, complete the setup. + if (!DatabaseManager.getManager().getMainCalendar(settings.getGuildID()).getCalendarAddress().equalsIgnoreCase("primary")) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } else if (settings.getEncryptedAccessToken().equalsIgnoreCase("N/a") && settings.getEncryptedRefreshToken().equalsIgnoreCase("N/a")) { + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Select.NotAuth", settings), event); + } else { + try { + Calendar service = CalendarAuth.getCalendarService(settings); + List items = service.calendarList().list().setMinAccessRole("writer").execute().getItems(); + boolean valid = false; + for (CalendarListEntry i: items) { + if (!i.isDeleted() && i.getId().equals(args[0])) { + //valid + valid = true; + break; + } + } + if (valid) { + //Update and save. + CalendarData data = new CalendarData(event.getGuild().getLongID(), 1); + data.setCalendarId(args[0]); + data.setCalendarAddress(args[0]); + data.setExternal(true); + DatabaseManager.getManager().updateCalendar(data); + + //Update guild settings + settings.setUseExternalCalendar(true); + DatabaseManager.getManager().updateSettings(settings); + + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Select.Success", settings), event); + } else { + //Invalid + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Select.Failure.Invalid", settings), event); + } + } catch (Exception e) { + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Select.Failure.Unknown", settings), event); + Logger.getLogger().exception(event.getAuthor(), "Failed to connect external calendar!", e, this.getClass(), true); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("AddCalendar.Specify", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.MANAGE_SERVER", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Patron", settings), event); + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AnnouncementCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AnnouncementCommand.java new file mode 100644 index 00000000..38e92a3e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/AnnouncementCommand.java @@ -0,0 +1,1358 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.announcement.AnnouncementType; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import com.cloudcraftgaming.discal.api.object.announcement.AnnouncementCreatorResponse; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.api.utils.AnnouncementUtils; +import com.cloudcraftgaming.discal.api.utils.EventUtils; +import com.cloudcraftgaming.discal.api.utils.GeneralUtils; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.bot.module.announcement.AnnouncementCreator; +import com.cloudcraftgaming.discal.bot.module.announcement.AnnouncementMessageFormatter; +import com.cloudcraftgaming.discal.bot.utils.ChannelUtils; +import com.cloudcraftgaming.discal.bot.utils.RoleUtils; +import com.cloudcraftgaming.discal.bot.utils.UserUtils; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.*; +import sx.blah.discord.util.EmbedBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Created by Nova Fox on 3/4/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("Duplicates") +public class AnnouncementCommand implements ICommand { + + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "Announcement"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + ArrayList aliases = new ArrayList<>(); + aliases.add("announcements"); + aliases.add("announce"); + aliases.add("alert"); + aliases.add("alerts"); + aliases.add("a"); + aliases.add("ann"); + return aliases; + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("announcement"); + info.setDescription("Used for all announcement functions."); + info.setExample("!announcement (value(s))"); + + info.getSubCommands().put("create", "Starts the announcement creator."); + info.getSubCommands().put("copy", "Copies an existing announcement."); + info.getSubCommands().put("edit", "Edits an existing announcement."); + info.getSubCommands().put("confirm", "Confirms and creates/edits the announcement."); + info.getSubCommands().put("cancel", "Cancels the current announcement creator/editor"); + info.getSubCommands().put("delete", "Deletes an existing announcement."); + info.getSubCommands().put("view", "Views the specified announcement."); + info.getSubCommands().put("review", "Reviews the announcement in the creator/editor."); + info.getSubCommands().put("subscribe", "Subscribes users/roles to the announcement."); + info.getSubCommands().put("sub", "Subscribes users/roles to the announcement."); + info.getSubCommands().put("unsubscribe", "Unsubscribes users/roles to the announcement."); + info.getSubCommands().put("unsub", "Unsubscribes users/roles to the announcement."); + info.getSubCommands().put("channel", "Sets the channel the announcement will be sent in."); + info.getSubCommands().put("type", "Sets the announcement's type."); + info.getSubCommands().put("hours", "Sets the amount of hours before the event to fire (added to minutes)"); + info.getSubCommands().put("minutes", "Sets the amount of minutes before the event to fire (added to hours)"); + info.getSubCommands().put("list", "Lists an amount of events."); + info.getSubCommands().put("event", "Sets the event the announcement is for (if applicable)"); + info.getSubCommands().put("color", "Sets the color the announcement is for (if applicable)"); + info.getSubCommands().put("info", "Sets an additional info."); + info.getSubCommands().put("enable", "Enables or Disables the announcement (alias for `disable`)"); + info.getSubCommands().put("disable", "Enables or Disables the announcement (alias for `enable`)"); + info.getSubCommands().put("infoOnly", "Allows for setting an announcement to ONLY display the ' extra info'"); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length < 1) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Few", settings), event); + } else { + switch (args[0].toLowerCase()) { + case "create": + if (PermissionChecker.hasSufficientRole(event)) + moduleCreate(event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "confirm": + if (PermissionChecker.hasSufficientRole(event)) + moduleConfirm(event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "cancel": + if (PermissionChecker.hasSufficientRole(event)) + moduleCancel(event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "delete": + if (PermissionChecker.hasSufficientRole(event)) + moduleDelete(args, event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "view": + case "review": + moduleView(args, event, settings); + break; + case "subscribe": + case "sub": + moduleSubscribeRewrite(args, event, settings); + break; + case "unsubscribe": + case "unsub": + moduleUnsubscribeRewrite(args, event, settings); + break; + case "type": + moduleType(args, event, settings); + break; + case "hours": + moduleHours(args, event, settings); + break; + case "minutes": + moduleMinutes(args, event, settings); + break; + case "list": + moduleList(args, event, settings); + break; + case "event": + moduleEvent(args, event, settings); + break; + case "info": + moduleInfo(args, event, settings); + break; + case "enable": + case "enabled": + case "disable": + case "disabled": + moduleEnable(args, event, settings); + break; + case "infoonly": + moduleInfoOnly(args, event, settings); + case "channel": + moduleChannel(args, event, settings); + break; + case "color": + case "colour": + moduleColor(args, event, settings); + break; + case "copy": + if (PermissionChecker.hasSufficientRole(event)) + moduleCopy(args, event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "edit": + if (PermissionChecker.hasSufficientRole(event)) + moduleEdit(args, event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + default: + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Invalid", settings), event); + break; + } + } + return false; + } + + + private void moduleCreate(MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + AnnouncementCreator.getCreator().init(event, settings); + if (!AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Create.Init", settings), event); + else + MessageManager.deleteMessage(event); + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event)); + + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event); + } + } + } + + private void moduleEdit(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (args.length == 2) { + String anId = args[1]; + if (AnnouncementUtils.announcementExists(anId, event)) { + Announcement announcement = AnnouncementCreator.getCreator().edit(event, anId, settings); + + if (announcement.getCreatorMessage() == null) { + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(announcement, settings), MessageManager.getMessage("Creator.Announcement.Edit.Init", settings), event); + } else { + MessageManager.deleteMessage(event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Edit.Specify", settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event); + } + } + } + + private void moduleConfirm(MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + AnnouncementCreatorResponse acr = AnnouncementCreator.getCreator().confirmAnnouncement(event); + if (acr.isSuccessful()) { + if (acr.getAnnouncement().isEditing()) { + if (acr.getAnnouncement().getCreatorMessage() != null) { + MessageManager.deleteMessage(acr.getAnnouncement().getCreatorMessage()); + MessageManager.deleteMessage(event); + } + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(acr.getAnnouncement(), settings), MessageManager.getMessage("Creator.Announcement.Confirm.Edit.Success", settings), event); + } else { + if (acr.getAnnouncement().getCreatorMessage() != null) { + MessageManager.deleteMessage(acr.getAnnouncement().getCreatorMessage()); + MessageManager.deleteMessage(event); + } + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(acr.getAnnouncement(), settings), MessageManager.getMessage("Creator.Announcement.Confirm.Create.Success", settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Confirm.Failure", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Confirm.Failure", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } + + private void moduleCancel(MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + IMessage creatorMessage = AnnouncementCreator.getCreator().getCreatorMessage(guildId); + AnnouncementCreator.getCreator().terminate(event); + + if (creatorMessage != null) { + MessageManager.deleteMessage(creatorMessage); + MessageManager.deleteMessage(event); + } + + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Cancel.Success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } + + private void moduleDelete(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 1) { + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Delete.Specify", settings), event); + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Delete.InCreator", settings), event)); + } + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Delete.InCreator", settings), event); + } + } else if (args.length == 2) { + String value = args[1]; + if (AnnouncementUtils.announcementExists(value, event)) { + if (DatabaseManager.getManager().deleteAnnouncement(value)) { + + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Delete.Success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Delete.Failure", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Delete.Specify", settings), event); + } + } + + private void moduleView(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 1) { + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), event)); + } else { + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.View.Specify", settings), event); + } + } else if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.View.InCreator", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.View.InCreator", settings), event); + } + } else { + try { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guildId); + if (a != null) { + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), AnnouncementMessageFormatter.getSubscriberNames(a), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } catch (Exception e) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.View.Specify", settings), event); + } + } + + @Deprecated + @SuppressWarnings("unused") + private void moduleSubscribe(String[] args, MessageReceivedEvent event) { + long guildId = event.getGuild().getLongID(); + if (args.length == 1) { + MessageManager.sendMessage("Please specify the ID of the announcement you wish to subscribe to!", + event); + } else if (args.length == 2) { + String value = args[1]; + if (AnnouncementUtils.announcementExists(value, event)) { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guildId); + String senderId = event.getMessage().getAuthor().getStringID(); + if (!a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().add(senderId); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("You have subscribed to the announcement with the ID: `" + value + "`" + MessageManager.lineBreak + "To unsubscribe use `!announcement unsubscribe `", event); + } else { + MessageManager.sendMessage("You are already subscribed to that event!", event); + } + } else { + MessageManager.sendMessage("Hmm.. it seems the specified announcement does not exist, are you sure you wrote the ID correctly?", event); + } + } else if (args.length == 3) { + String value1 = args[1]; + String value2 = args[2]; + if (AnnouncementUtils.announcementExists(value1, event)) { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value1), guildId); + IUser user = event.getMessage().getGuild().getUserByID(UserUtils.getUser(value2, event.getMessage())); + if (user != null) { + //Valid user, let's add that user to the announcement. + if (!a.getSubscriberUserIds().contains(user.getStringID())) { + String username = user.getDisplayName(event.getMessage().getGuild()); + a.getSubscriberUserIds().add(user.getStringID()); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + username + "` has been subscribed to the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To unsubscribe them use `!announcement unsubscribe ", event); + } else { + MessageManager.sendMessage("That user is already subscribed to the specified announcement! To unsubscribe them use `!announcement unsubscribe `", event); + } + } else if (value2.equalsIgnoreCase("everyone") || value2.equalsIgnoreCase("here")) { + //Here or everyone is to be subscribed... + String men = value2.toLowerCase(); + if (!a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().add(men); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + men + "` has been subscribed to the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To unsubscribe them use `!announcement unsubscribe ", event); + } else { + MessageManager.sendMessage(men + " is already subscribed to the specified announcement! To unsubscribe them use `!announcement unsubscribe `", event); + } + } else { + //User does not exist, see if a role. + IRole role = RoleUtils.getRoleFromMention(value2, event); + if (role != null) { + //Role valid, let's add that role to the announcement. + if (!a.getSubscriberRoleIds().contains(role.getStringID())) { + String roleName = role.getName(); + a.getSubscriberRoleIds().add(role.getStringID()); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + roleName + "` has been subscribed to the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To unsubscribe them use `!announcement unsubscribe ", event); + } else { + MessageManager.sendMessage("That role is already subscribed to the specified announcement! To unsubscribe them use `!announcement unsubscribe `", event); + } + } else { + //Role does not exist... + MessageManager.sendMessage("Role or user not found! Are you sure you typed them correctly?", event); + } + } + } else { + MessageManager.sendMessage("Hmm.. it seems the specified announcement does not exist, are you sure you wrote the ID correctly?", event); + } + } else { + MessageManager.sendMessage("Please use `!announcement subscribe ` or `!announcement subscribe `", event); + } + } + + private void moduleSubscribeRewriteArgsOne(MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + IUser user = message.getAuthor(); + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + Announcement a = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + String senderId = user.getStringID(); + if (!a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().add(senderId); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Success", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Success", settings), event); + } + } else { + //Announcement contains user ID + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Already", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Already", settings), event); + } + } + } else { + //User not creating an announcement + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Specify", settings), event); + } + } + + private void moduleSubscribeRewriteArgsTwo(String[] args, MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + IUser user = message.getAuthor(); + String value = args[1]; + if (args[1].length() <= 32) { + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + Announcement a = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + IUser u = guild.getUserByID(UserUtils.getUser(value, message)); + IRole r = guild.getRoleByID(RoleUtils.getRole(value, message)); + if (value.equalsIgnoreCase("everyone") || value.equalsIgnoreCase("here")) { + String men = value.toLowerCase(); + if (!a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().add(men); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", men, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", men, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", men, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", men, settings), event); + } + } + } else if (u != null) { + String username = u.getName(); + if (!a.getSubscriberUserIds().contains(u.getStringID())) { + a.getSubscriberUserIds().add(u.getStringID()); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", username, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", username, settings), event); + } + } + } else if (r != null) { + String username = r.getName(); + if (!a.getSubscriberRoleIds().contains(r.getStringID())) { + a.getSubscriberRoleIds().add(r.getStringID()); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", username, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", username, settings), event); + } + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Specify", settings), event); + } + } else { + if (AnnouncementUtils.announcementExists(value, event)) { + String senderId = user.getStringID(); + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guild.getLongID()); + if (!a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().add(senderId); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Self.Already", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } + } + + private void moduleSubscribeRewriteArgsThree(String[] args, MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + List subscribedUsers = new ArrayList<>(); + List subscribedRoles = new ArrayList<>(); + + String announcementID; + boolean updateDb; + if (args[1].length() > 32) { + AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + updateDb = true; + announcementID = args[1]; + } else { + updateDb = false; + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + announcementID = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()).getAnnouncementId().toString(); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Specify", settings), event); + return; + } + } + + if (AnnouncementUtils.announcementExists(announcementID, event) || !updateDb) { + Announcement a = updateDb ? DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementID), guild.getLongID()) : AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + + for (int i = 1; i < args.length; i++) { + IUser u = guild.getUserByID(UserUtils.getUser(args[i].matches("<@?!?#?&?[0-9]+>") ? args[i].replaceAll("<@?!?#?&?[0-9]+>", "") : args[i], event.getGuild())); + IRole r = guild.getRoleByID(RoleUtils.getRole(args[i].matches("<@?!?#?&?[0-9]+>") ? args[i].replaceAll("<@?!?#?&?[0-9]+>", "") : args[i], event.getGuild())); + if (args[i].equalsIgnoreCase("everyone") || args[i].equalsIgnoreCase("here")) { + //Here or everyone is to be subscribed... + String men = args[i].toLowerCase(); + if (!a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().add(men); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Success", "%value%", men, settings), event); + subscribedUsers.add(men); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Subscribe.Other.Already", "%value%", men, settings), event); + } + } + + if (u != null) { + if (!a.getSubscriberUserIds().contains(u.getStringID())) { + subscribedUsers.add(u.getName()); + a.getSubscriberUserIds().add(u.getStringID()); + } + } else if (r != null) { + if (!a.getSubscriberRoleIds().contains(r.getStringID())) { + subscribedRoles.add(r.getName()); + a.getSubscriberRoleIds().add(r.getStringID()); + } + } + } + + EmbedBuilder em = new EmbedBuilder(); + em.withColor(EventColor.TURQUOISE.getR(), EventColor.TURQUOISE.getG(), EventColor.TURQUOISE.getB()); + em.withAuthorIcon(event.getClient().getApplicationIconURL()); + em.withAuthorName(MessageManager.getMessage("Embed.Announcement.Subscribe.Title", settings)); + em.withDesc(MessageManager.getMessage("Embed.Announcement.Subscribe.Users", "%users%", subscribedUsers.toString(), settings) + MessageManager.lineBreak + MessageManager.getMessage("Embed.Announcement.Subscribe.Roles", "%roles%", subscribedRoles.toString(), settings)); + em.withFooterText(MessageManager.getMessage("Embed.Announcement.Subscribe.Footer", "%id%", a.getAnnouncementId().toString(), settings)); + MessageManager.sendMessage(em.build(), event); + if (updateDb) + DatabaseManager.getManager().updateAnnouncement(a); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } + + private void moduleSubscribeRewrite(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 1) + moduleSubscribeRewriteArgsOne(event, settings); + else if (args.length == 2) + moduleSubscribeRewriteArgsTwo(args, event, settings); + else + moduleSubscribeRewriteArgsThree(args, event, settings); + } + + private void moduleUnsubscribeRewriteArgsOne(MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + IUser user = message.getAuthor(); + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + Announcement a = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + String senderId = user.getStringID(); + if (a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().remove(senderId); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Success", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Success", settings), event); + } + } else { // Announcement does not contain user ID + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Not", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Not", settings), event); + } + } + } else { // User not creating an announcement + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Specify", settings), event); + } + } + + private void moduleUnsubscribeRewriteArgsTwo(String[] args, MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + IUser user = message.getAuthor(); + String value = args[1]; + if (args[1].length() <= 32) { + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + Announcement a = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + IUser u = guild.getUserByID(UserUtils.getUser(value.matches("<@?!?#?&?[0-9]+>") ? value.replaceAll("<@?!?#?&?[0-9]+>", "") : value, event.getGuild())); + IRole r = guild.getRoleByID(RoleUtils.getRole(value.matches("<@?!?#?&?[0-9]+>") ? value.replaceAll("<@?!?#?&?[0-9]+>", "") : value, event.getGuild())); + if (value.equalsIgnoreCase("everyone") || value.equalsIgnoreCase("here")) { + String men = value.toLowerCase(); + if (a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().remove(men); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", men, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", men, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", men, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", men, settings), event); + } + } + } else if (u != null) { + String username = u.getName(); + if (a.getSubscriberUserIds().contains(u.getStringID())) { + a.getSubscriberUserIds().remove(u.getStringID()); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", username, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", username, settings), event); + } + } + } else if (r != null) { + String username = r.getName(); + if (a.getSubscriberRoleIds().contains(r.getStringID())) { + a.getSubscriberRoleIds().remove(r.getStringID()); + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", username, settings), event); + } + } else { + if (a.getCreatorMessage() != null) { + MessageManager.deleteMessage(a.getCreatorMessage()); + MessageManager.deleteMessage(event); + a.setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", username, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", username, settings), event); + } + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Specify", settings), event); + } + } else { + if (AnnouncementUtils.announcementExists(value, event)) { + String senderId = user.getStringID(); + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guild.getLongID()); + if (!a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().remove(senderId); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Self.Not", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } + } + + private void moduleUnsubscribeRewriteArgsThree(String[] args, MessageReceivedEvent event, GuildSettings settings) { + IMessage message = event.getMessage(); + IGuild guild = message.getGuild(); + List subscribedUsers = new ArrayList<>(); + List subscribedRoles = new ArrayList<>(); + + String announcementID; + boolean updateDb; + if (args[1].length() > 32) { + AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + updateDb = true; + announcementID = args[1]; + } else { + updateDb = false; + if (AnnouncementCreator.getCreator().hasAnnouncement(guild.getLongID())) { + announcementID = AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()).getAnnouncementId().toString(); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Specify", settings), event); + return; + } + } + + if (AnnouncementUtils.announcementExists(announcementID, event) || !updateDb) { + Announcement a = updateDb ? DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementID), guild.getLongID()) : AnnouncementCreator.getCreator().getAnnouncement(guild.getLongID()); + + for (int i = 1; i < args.length; i++) { + IUser u = guild.getUserByID(UserUtils.getUser(args[i].matches("<@?!?#?&?[0-9]+>") ? args[i].replaceAll("<@?!?#?&?[0-9]+>", "") : args[i], event.getGuild())); + IRole r = guild.getRoleByID(RoleUtils.getRole(args[i].matches("<@?!?#?&?[0-9]+>") ? args[i].replaceAll("<@?!?#?&?[0-9]+>", "") : args[i], event.getGuild())); + if (args[i].toLowerCase().contains("everyone") || args[i].toLowerCase().contains("here")) { + //Here or everyone is to be subscribed... + String men = args[i].toLowerCase(); + if (a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().remove(men); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Success", "%value%", men, settings), event); + subscribedUsers.add(men); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Unsubscribe.Other.Not", "%value%", men, settings), event); + } + } + + if (u != null) { + if (a.getSubscriberUserIds().contains(u.getStringID())) { + subscribedUsers.add(u.getName()); + a.getSubscriberUserIds().remove(u.getStringID()); + } + } else if (r != null) { + if (a.getSubscriberRoleIds().contains(r.getStringID())) { + subscribedRoles.add(r.getName()); + a.getSubscriberRoleIds().remove(r.getStringID()); + } + } + } + + EmbedBuilder em = new EmbedBuilder(); + em.withColor(EventColor.TURQUOISE.getR(), EventColor.TURQUOISE.getG(), EventColor.TURQUOISE.getB()); + em.withAuthorIcon(event.getClient().getApplicationIconURL()); + em.withAuthorName(MessageManager.getMessage("Embed.Announcement.Unsubscribe.Title", settings)); + em.withDesc(MessageManager.getMessage("Embed.Announcement.Unsubscribe.Users", "%users%", subscribedUsers.toString(), settings) + MessageManager.lineBreak + MessageManager.getMessage("Embed.Announcement.Unsubscribe.Roles", "%roles%", subscribedRoles.toString(), settings)); + em.withFooterText(MessageManager.getMessage("Embed.Announcement.Unsubscribe.Footer", "%id%", a.getAnnouncementId().toString(), settings)); + MessageManager.sendMessage(em.build(), event); + if (updateDb) + DatabaseManager.getManager().updateAnnouncement(a); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + + } + + private void moduleUnsubscribeRewrite(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 1) + moduleUnsubscribeRewriteArgsOne(event, settings); + else if (args.length == 2) + moduleUnsubscribeRewriteArgsTwo(args, event, settings); + else + moduleUnsubscribeRewriteArgsThree(args, event, settings); + } + + @Deprecated + @SuppressWarnings("unused") + private void moduleUnsubscribe(String[] args, MessageReceivedEvent event) { + long guildId = event.getGuild().getLongID(); + if (args.length == 1) { + MessageManager.sendMessage("Please specify the ID of the announcement you wish to unsubscribe from!", event); + } else if (args.length == 2) { + String value = args[1]; + if (AnnouncementUtils.announcementExists(value, event)) { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guildId); + String senderId = event.getMessage().getAuthor().getStringID(); + if (a.getSubscriberUserIds().contains(senderId)) { + a.getSubscriberUserIds().remove(senderId); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("You have unsubscribed to the announcement with the ID: `" + value + "`" + MessageManager.lineBreak + "To re-subscribe use `!announcement subscribe `", event); + } else { + MessageManager.sendMessage("You are not subscribed to this event!", event); + } + } else { + MessageManager.sendMessage("Hmm.. it seems the specified announcement does not exist, are you sure you wrote the ID correctly?", event); + } + } else if (args.length == 3) { + String value1 = args[1]; + String value2 = args[2]; + if (AnnouncementUtils.announcementExists(value1, event)) { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value1), guildId); + IUser user = UserUtils.getUserFromMention(value2, event); + if (user != null) { + //Valid user, let's add that user to the announcement. + if (a.getSubscriberUserIds().contains(user.getStringID())) { + String username = user.getDisplayName(event.getMessage().getGuild()); + a.getSubscriberUserIds().remove(user.getStringID()); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + username + "` has been unsubscribed from the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To re-subscribe them use `!announcement subscribe ", event); + } else { + MessageManager.sendMessage("That user is not subscribed to the specified announcement! To subscribe them use `!announcement unsubscribe `", event); + } + } else if (value2.equalsIgnoreCase("everyone") || value2.equalsIgnoreCase("here")) { + //Here or everyone is to be mentioned... + String men = value2.toLowerCase(); + if (a.getSubscriberRoleIds().contains(men)) { + a.getSubscriberRoleIds().remove(men); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + men + "` has been unsubscribed from the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To re-subscribe them use `!announcement subscribe ", event); + } else { + MessageManager.sendMessage(men + " is not subscribed to the specified announcement! To subscribe them use `!announcement unsubscribe `", event); + } + } else { + //User does not exist, see if a role. + IRole role = RoleUtils.getRoleFromMention(value2, event); + if (role != null) { + //Role valid, let's add that role to the announcement. + if (a.getSubscriberRoleIds().contains(role.getStringID())) { + String roleName = role.getName(); + a.getSubscriberRoleIds().remove(role.getStringID()); + DatabaseManager.getManager().updateAnnouncement(a); + MessageManager.sendMessage("`" + roleName + "` has been unsubscribed from the announcement with the ID `" + a.getAnnouncementId() + "`" + MessageManager.lineBreak + "To re-subscribe them use `!announcement subscribe ", event); + } else { + MessageManager.sendMessage("That role is not subscribed to the specified announcement! To subscribe them use `!announcement unsubscribe `", event); + } + } else { + //Role does not exist... + MessageManager.sendMessage("Role or user not found! Are you sure you typed them correctly?", event); + } + } + } else { + MessageManager.sendMessage("Hmm.. it seems the specified announcement does not exist, are you sure you wrote the ID correctly?", event); + } + } else { + MessageManager.sendMessage("Please use `!announcement unsubscribe ` or `!announcement unsubscribe `", event); + } + } + + private void moduleType(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementType.isValid(value)) { + AnnouncementType type = AnnouncementType.fromValue(value); + AnnouncementCreator.getCreator().getAnnouncement(guildId).setAnnouncementType(type); + if (type.equals(AnnouncementType.SPECIFIC)) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Type.Success.Specific", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Success.Specific", settings), event); + } + } else if (type.equals(AnnouncementType.COLOR)) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Type.Success.Color", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Success.Color", settings), event); + } + } else if (type.equals(AnnouncementType.RECUR)) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Type.Success.Recur", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Success.Recur", settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Type.Success.Universal", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Success.Universal", settings), event); + } + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Type.Specify", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Specify", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Type.Specify", settings), event); + } + } + + private void moduleHours(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + try { + Integer hoursOr = Integer.valueOf(value); + Integer hours = Math.abs(hoursOr); + AnnouncementCreator.getCreator().getAnnouncement(guildId).setHoursBefore(hours); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Hours.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Hours.Success", "%hours%", hours + "", settings), event); + } + } catch (NumberFormatException e) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Hours.NotInt", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Hours.NotInt", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Hours.Specify", settings), event); + } + } + + private void moduleMinutes(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + try { + int minutesOr = Integer.valueOf(value); + int minutes = Math.abs(minutesOr); + AnnouncementCreator.getCreator().getAnnouncement(guildId).setMinutesBefore(minutes); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Minutes.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Minutes.Success", "%minutes%", minutes + "", settings), event); + } + } catch (NumberFormatException e) { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Minutes.NotInt", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Minutes.NotInt", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Minutes.Specify", settings), event); + } + } + + private void moduleList(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 1) { + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.Specify", settings), event); + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.List.InCreator", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.InCreator", settings), event); + } + } + } else if (args.length == 2) { + String value = args[1]; + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (value.equalsIgnoreCase("all")) { + ArrayList announcements = DatabaseManager.getManager().getAnnouncements(guildId); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.All", "%amount%", announcements.size() + "", settings), event); + //Loop and add embeds + for (Announcement a: announcements) { + MessageManager.sendMessage(AnnouncementMessageFormatter.getCondensedAnnouncementEmbed(a, settings), event); + } + } else { + //List specific amount of announcements + try { + Integer amount = Integer.valueOf(value); + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.Some", "%amount%", amount + "", settings), event); + + int posted = 0; + for (Announcement a: DatabaseManager.getManager().getAnnouncements(guildId)) { + if (posted < amount) { + MessageManager.sendMessage(AnnouncementMessageFormatter.getCondensedAnnouncementEmbed(a, settings), event); + + posted++; + } else { + break; + } + } + } catch (NumberFormatException e) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.NotInt", settings), event); + } + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.List.InCreator", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.InCreator", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.List.Specify", settings), event); + } + } + + private void moduleEvent(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementCreator.getCreator().getAnnouncement(guildId).getAnnouncementType().equals(AnnouncementType.SPECIFIC)) { + if (EventUtils.eventExists(settings, value)) { + AnnouncementCreator.getCreator().getAnnouncement(guildId).setEventId(value); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Event.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Event.Success", "%id%", value, settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.CannotFind.Event", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Event", settings), event); + } + } + } else if (AnnouncementCreator.getCreator().getAnnouncement(guildId).getAnnouncementType().equals(AnnouncementType.RECUR)) { + if (EventUtils.eventExists(settings, value)) { + if (value.contains("_")) { + String[] stuff = value.split("_"); + value = stuff[0]; + } + AnnouncementCreator.getCreator().getAnnouncement(guildId).setEventId(value); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Event.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Event.Success", "%id%", value, settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.CannotFind.Event", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Event", settings), event); + } + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Event.Failure.Type", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Event.Failure.Type", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Event.Specify", settings), event); + } + } + + private void moduleInfo(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length < 2) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Info.Specify", settings), event); + } else if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + AnnouncementCreator.getCreator().getAnnouncement(guildId).setInfo(value); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Info.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Info.Success", "%info%", value, settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + String value = GeneralUtils.getContent(args, 1); + AnnouncementCreator.getCreator().getAnnouncement(guildId).setInfo(value); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Info.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Info.Success", "%info%", value, settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } + } + + private void moduleEnable(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + MessageManager.sendMessage(MessageManager.getMessage("Announcement.Enable.Creator", settings), event); + } else { + String value = args[1]; + if (!AnnouncementUtils.announcementExists(value, event)) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } else { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guildId); + a.setEnabled(!a.isEnabled()); + + DatabaseManager.getManager().updateAnnouncement(a); + + MessageManager.sendMessage(MessageManager.getMessage("Announcement.Enable.Success", "%value%", a.isEnabled() + "", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Announcement.Enable.Specify", settings), event); + } + } + + private void moduleInfoOnly(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + MessageManager.sendMessage(MessageManager.getMessage("Announcement.InfoOnly.Creator", settings), event); + } else { + String value = args[1]; + if (!AnnouncementUtils.announcementExists(value, event)) { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } else { + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(value), guildId); + a.setInfoOnly(!a.isInfoOnly()); + + DatabaseManager.getManager().updateAnnouncement(a); + + MessageManager.sendMessage(MessageManager.getMessage("Announcement.InfoOnly.Success", "%value%", a.isInfoOnly() + "", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Announcement.InfoOnly.Specify", settings), event); + } + } + + private void moduleChannel(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (ChannelUtils.channelExists(value, event)) { + IChannel c = ChannelUtils.getChannelFromNameOrId(value, event); + if (c != null) { + AnnouncementCreator.getCreator().getAnnouncement(guildId).setAnnouncementChannelId(c.getStringID()); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Channel.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Channel.Success", "%channel%", c.getName(), settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.CannotFind.Channel", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Channel", settings), event); + } + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.CannotFind.Channel", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Channel", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Channel.Specify", settings), event); + } + } + + private void moduleColor(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementCreator.getCreator().getAnnouncement(guildId).getAnnouncementType().equals(AnnouncementType.COLOR)) { + if (EventColor.exists(value)) { + EventColor color = EventColor.fromNameOrHexOrID(value); + AnnouncementCreator.getCreator().getAnnouncement(guildId).setEventColor(color); + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Color.Success.New", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Color.Success", "%color%", color.name(), settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Color.Specify", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Color.Specify", settings), event); + } + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.Color.Failure.Type", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Color.Failure.Type", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.NotInit", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Color.Specify", settings), event); + } + } + + private void moduleCopy(String[] args, MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (!AnnouncementCreator.getCreator().hasAnnouncement(guildId)) { + if (AnnouncementUtils.announcementExists(value, event)) { + Announcement a = AnnouncementCreator.getCreator().init(event, value, settings); + + if (a.getCreatorMessage() == null) { + MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(a, settings), MessageManager.getMessage("Creator.Announcement.Copy.Success", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.CannotFind.Announcement", settings), event); + } + } else { + if (AnnouncementCreator.getCreator().hasCreatorMessage(guildId)) { + MessageManager.deleteMessage(AnnouncementCreator.getCreator().getCreatorMessage(guildId)); + MessageManager.deleteMessage(event); + AnnouncementCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(AnnouncementMessageFormatter.getFormatAnnouncementEmbed(AnnouncementCreator.getCreator().getAnnouncement(guildId), settings), MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.AlreadyInit", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Announcement.Copy.Specify", settings), event); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CalendarCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CalendarCommand.java new file mode 100644 index 00000000..8246d65b --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CalendarCommand.java @@ -0,0 +1,450 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.message.calendar.CalendarMessageFormatter; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarCreatorResponse; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.calendar.PreCalendar; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.api.utils.CalendarUtils; +import com.cloudcraftgaming.discal.api.utils.GeneralUtils; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.bot.internal.calendar.calendar.CalendarCreator; +import com.cloudcraftgaming.discal.bot.utils.TimeZoneUtils; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IMessage; +import sx.blah.discord.handle.obj.Permissions; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/4/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings({"FieldCanBeLocal", "Duplicates"}) +public class CalendarCommand implements ICommand { + private String TIME_ZONE_DB = "http://www.joda.org/joda-time/timezones.html"; + + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "calendar"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + ArrayList aliases = new ArrayList<>(); + aliases.add("cal"); + aliases.add("callador"); + return aliases; + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("calendar"); + info.setDescription("Used for direct interaction with your DisCal Calendar."); + info.setExample("!calendar (value)"); + + info.getSubCommands().put("create", "Starts the creation of a new calendar."); + info.getSubCommands().put("cancel", "Cancels the creator/editor"); + info.getSubCommands().put("view", "Views the calendar in the creator/editor"); + info.getSubCommands().put("review", "Views the calendar in the creator/editor"); + info.getSubCommands().put("confirm", "Confirms and creates/edits the calendar."); + info.getSubCommands().put("delete", "Deletes the calendar"); + info.getSubCommands().put("remove", "Deletes the calendar"); + info.getSubCommands().put("name", "Sets the calendar's name/summary"); + info.getSubCommands().put("summary", "Sets the calendar's name/summary"); + info.getSubCommands().put("description", "Sets the calendar's description"); + info.getSubCommands().put("timezone", "Sets teh calendar's timezone."); + info.getSubCommands().put("edit", "Edits the calendar."); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length < 1) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Few", settings), event); + } else { + long guildId = event.getGuild().getLongID(); + //TODO: Add support for multiple calendars... + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(guildId); + + switch (args[0].toLowerCase()) { + case "create": + if (PermissionChecker.hasSufficientRole(event)) + moduleCreate(args, event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "cancel": + if (PermissionChecker.hasSufficientRole(event)) + moduleCancel(event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "view": + moduleView(event, calendarData, settings); + break; + case "review": + moduleView(event, calendarData, settings); + break; + case "confirm": + if (PermissionChecker.hasSufficientRole(event)) + moduleConfirm(event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "delete": + if (PermissionChecker.hasSufficientRole(event)) + moduleDelete(event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "remove": + if (PermissionChecker.hasSufficientRole(event)) + moduleDelete(event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + case "name": + moduleSummary(args, event, calendarData, settings); + break; + case "summary": + moduleSummary(args, event, calendarData, settings); + break; + case "description": + moduleDescription(args, event, calendarData, settings); + break; + case "timezone": + moduleTimezone(args, event, calendarData, settings); + break; + case "edit": + if (PermissionChecker.hasSufficientRole(event)) + moduleEdit(event, calendarData, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + break; + default: + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Invalid", settings), event); + break; + } + } + return false; + } + + private void moduleCreate(String[] args, MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.AlreadyInit", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.AlreadyInit", settings), event); + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) { + if (args.length > 1) { + String name = GeneralUtils.getContent(args, 1); + PreCalendar calendar = CalendarCreator.getCreator().init(event, name, settings, true); + if (calendar.getCreatorMessage() != null) + MessageManager.deleteMessage(event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Create.Init", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Create.Name", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } + } + + private void moduleCancel(MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + IMessage message = CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage(); + boolean editing = CalendarCreator.getCreator().getPreCalendar(guildId).isEditing(); + if (CalendarCreator.getCreator().terminate(event)) { + if (message != null) { + if (!editing) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + } else { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Cancel.Edit.Success", settings), event)); + } + } else { + if (!editing) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Cancel.Success", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Cancel.Edit.Success", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Cancel.Failure", settings), event); + MessageManager.deleteMessage(event); + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NotInit", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } + + private void moduleView(MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + PreCalendar preCalendar = CalendarCreator.getCreator().getPreCalendar(guildId); + if (preCalendar.getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Review", settings), event)); + } else { + MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(preCalendar, settings), MessageManager.getMessage("Creator.Calendar.Review", settings), event); + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } + + private void moduleConfirm(MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + CalendarCreatorResponse response = CalendarCreator.getCreator().confirmCalendar(event, settings); + if (response.isSuccessful()) { + if (response.isEdited()) { + if (response.getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getCalendarLinkEmbed(response.getCalendar(), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Edit.Success", settings), event)); + } else { + MessageManager.sendMessage(CalendarMessageFormatter.getCalendarLinkEmbed(response.getCalendar(), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Edit.Success", settings), event); + } + } else { + if (response.getCalendar() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getCalendarLinkEmbed(response.getCalendar(), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Create.Success", settings), event)); + } else { + MessageManager.sendMessage(CalendarMessageFormatter.getCalendarLinkEmbed(response.getCalendar(), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Create.Success", settings), event); + } + } + } else { + if (response.isEdited()) { + if (response.getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Edit.Failure", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Confirm.Edit.Failure", settings), event); + } + } else { + if (response.getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Confirm.Create.Failure", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Confirm.Create.Failure", settings), event); + } + } + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } + + private void moduleDelete(MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getMessage().getGuild().getLongID(); + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Delete.Failure.InCreator", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Delete.Failure.InCreator", settings), event); + } + return; + } + if (!event.getMessage().getAuthor().getPermissionsForGuild(event.getMessage().getGuild()).contains(Permissions.MANAGE_SERVER)) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.MANAGE_SERVER", settings), event); + return; + } + if (!calendarData.getCalendarId().equalsIgnoreCase("primary")) { + //Delete calendar + if (CalendarUtils.deleteCalendar(calendarData, settings)) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Delete.Success", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Delete.Failure.Unknown", settings), event); + } else { + //No calendar to delete + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Delete.Failure.NoCalendar", settings), event); + } + } + + private void moduleSummary(String[] args, MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length > 1) { + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + CalendarCreator.getCreator().getPreCalendar(guildId).setSummary(GeneralUtils.getContent(args, 1)); + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Summary.N.Success", settings), event)); + } else { + String msg = MessageManager.getMessage("Creator.Calendar.Summary.O.Success", "%summary%", GeneralUtils.getContent(args, 1), settings); + MessageManager.sendMessage(msg, event); + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } else { + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Summary.Specify", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Summary.Specify", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Summary.Specify", settings), event); + } + } + } + + private void moduleDescription(String[] args, MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length > 1) { + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + CalendarCreator.getCreator().getPreCalendar(guildId).setDescription(GeneralUtils.getContent(args, 1)); + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Description.N.Success", settings) + TIME_ZONE_DB, event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Description.O.Success", "%desc%", GeneralUtils.getContent(args, 1), settings) + TIME_ZONE_DB, event); + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } else { + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.Description.Specify", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Description.Specify", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.Description.Specify", settings), event); + } + } + } + + private void moduleTimezone(String[] args, MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (args.length == 2) { + String value = args[1]; + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (TimeZoneUtils.isValid(value)) { + CalendarCreator.getCreator().getPreCalendar(guildId).setTimezone(value); + + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.TimeZone.N.Success", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.TimeZone.O.Success", "%tz%", value, settings), event); + } + } else { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.TimeZone.Invalid", "%tz_db%", TIME_ZONE_DB, settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.TimeZone.Invalid", "%tz_db%", TIME_ZONE_DB, settings), event); + } + } + } else { + if (calendarData.getCalendarId().equalsIgnoreCase("primary")) + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.HasCalendar", settings), event); + } + } else { + if (CalendarCreator.getCreator().hasPreCalendar(guildId)) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.TimeZone.Specify", settings) + TIME_ZONE_DB, event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.TimeZone.Specify", settings) + TIME_ZONE_DB, event); + } + } + } + + private void moduleEdit(MessageReceivedEvent event, CalendarData calendarData, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + if (!CalendarCreator.getCreator().hasPreCalendar(guildId)) { + if (!calendarData.getCalendarAddress().equalsIgnoreCase("primary")) { + PreCalendar calendar = CalendarCreator.getCreator().edit(event, settings, true); + if (calendar.getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + } else { + MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(calendar, settings), MessageManager.getMessage("Creator.Calendar.Edit.Init", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + } + } else { + if (CalendarCreator.getCreator().getPreCalendar(guildId).getCreatorMessage() != null) { + MessageManager.deleteMessage(event); + MessageManager.deleteMessage(CalendarCreator.getCreator().getCreatorMessage(guildId)); + CalendarCreator.getCreator().setCreatorMessage(MessageManager.sendMessage(CalendarMessageFormatter.getPreCalendarEmbed(CalendarCreator.getCreator().getPreCalendar(guildId), settings), MessageManager.getMessage("Creator.Calendar.AlreadyInit", settings), event)); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.AlreadyInit", settings), event); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandExecutor.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandExecutor.java new file mode 100644 index 00000000..d4f3a268 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandExecutor.java @@ -0,0 +1,107 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.utils.GeneralUtils; +import sx.blah.discord.api.events.EventDispatcher; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class CommandExecutor { + private static CommandExecutor instance; + private final ArrayList commands = new ArrayList<>(); + + private CommandExecutor() { + } + + /** + * Gets the instance of the CommandExecutor. + * + * @return The instance of the CommandExecutor. + */ + public static CommandExecutor getExecutor() { + if (instance == null) + instance = new CommandExecutor(); + + return instance; + } + + /** + * Enables the CommandExecutor and sets up the Listener. + * + * @return The CommandExecutor's instance. + */ + public CommandExecutor enable() { + EventDispatcher dispatcher = DisCalAPI.getAPI().getClient().getDispatcher(); + dispatcher.registerListener(new CommandListener(this)); + return instance; + } + + + //Functionals + + /** + * Registers a command that can be executed. + * + * @param _command The command to register. + */ + public void registerCommand(ICommand _command) { + commands.add(_command); + } + + /** + * Issues a command if valid, else does nothing. + * + * @param cmd The Command to issue. + * @param argsOr The command arguments used. + * @param event The Event received. + */ + void issueCommand(String cmd, String[] argsOr, MessageReceivedEvent event, GuildSettings settings) { + + String[] args; + if (argsOr.length > 0) { + String toParse = GeneralUtils.getContent(argsOr, 0); + args = GeneralUtils.overkillParser(toParse).split(" "); + } else { + args = new String[0]; + } + + for (ICommand c: commands) { + if (c.getCommand().equalsIgnoreCase(cmd) || c.getAliases().contains(cmd.toLowerCase())) + c.issueCommand(args, event, settings); + } + + } + + /** + * Gets an ArrayList of all valid commands. + * + * @return An ArrayList of all valid commands. + */ + ArrayList getAllCommands() { + ArrayList cmds = new ArrayList<>(); + for (ICommand c: commands) { + if (!cmds.contains(c.getCommand())) + cmds.add(c.getCommand()); + } + return cmds; + } + + ArrayList getCommands() { + return commands; + } + + ICommand getCommand(String cmdNameOrAlias) { + for (ICommand c: commands) { + if (c.getCommand().equalsIgnoreCase(cmdNameOrAlias) || c.getAliases().contains(cmdNameOrAlias.toLowerCase())) + return c; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandListener.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandListener.java new file mode 100644 index 00000000..21135390 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/CommandListener.java @@ -0,0 +1,81 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.logger.Logger; +import sx.blah.discord.api.events.EventSubscriber; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Created by Nova Fox on 1/2/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +@SuppressWarnings("unused") +class CommandListener { + private CommandExecutor cmd; + + /** + * Creates a new CommandListener listener. + * + * @param _cmd The CommandExecutor instance to use. + */ + CommandListener(CommandExecutor _cmd) { + cmd = _cmd; + } + + /** + * Checks for command validity and calls the command executor if valid. + * + * @param event The event received to check for a command. + */ + @EventSubscriber + public void onMessageEvent(MessageReceivedEvent event) { + try { + if (event.getMessage() != null && event.getGuild() != null && event.getChannel() != null && !event.getChannel().isPrivate() && event.getMessage().getContent() != null && event.getMessage().getContent().length() > 0 && !event.getAuthor().isBot()) { + //Message is a valid guild message (not DM and not from a bot). Check if in correct channel. + GuildSettings settings = DatabaseManager.getManager().getSettings(event.getGuild().getLongID()); + if (event.getMessage().getContent().startsWith(settings.getPrefix())) { + if (PermissionChecker.isCorrectChannel(event)) { + //Prefixed with ! which should mean it is a command, convert and confirm. + String[] argsOr = event.getMessage().getContent().split("\\s+"); + if (argsOr.length > 1) { + ArrayList argsOr2 = new ArrayList<>(Arrays.asList(argsOr).subList(1, argsOr.length)); + String[] args = argsOr2.toArray(new String[argsOr2.size()]); + + String command = argsOr[0].replace(settings.getPrefix(), ""); + cmd.issueCommand(command, args, event, settings); + } else if (argsOr.length == 1) { + //Only command... no args. + cmd.issueCommand(argsOr[0].replace(settings.getPrefix(), ""), new String[0], event, settings); + } + } + } else if (!event.getMessage().mentionsEveryone() && !event.getMessage().mentionsHere() && (event.getMessage().toString().startsWith("<@" + DisCalAPI.getAPI().getClient().getOurUser().getStringID() + ">") || event.getMessage().toString().startsWith("<@!" + DisCalAPI.getAPI().getClient().getOurUser().getStringID() + ">"))) { + if (PermissionChecker.isCorrectChannel(event)) { + String[] argsOr = event.getMessage().getContent().split("\\s+"); + if (argsOr.length > 2) { + ArrayList argsOr2 = new ArrayList<>(Arrays.asList(argsOr).subList(2, argsOr.length)); + String[] args = argsOr2.toArray(new String[argsOr2.size()]); + + String command = argsOr[1]; + cmd.issueCommand(command, args, event, settings); + } else if (argsOr.length == 2) { + //No args... + cmd.issueCommand(argsOr[1], new String[0], event, settings); + } else if (argsOr.length == 1) { + //Only disCal mentioned... + cmd.issueCommand("DisCal", new String[0], event, settings); + } + } + } + } + } catch (Exception e) { + Logger.getLogger().exception(event.getAuthor(), "Command error; event message: " + event.getMessage().getContent(), e, this.getClass(), true); + } + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DevCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DevCommand.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DevCommand.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/command/DevCommand.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DisCalCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DisCalCommand.java new file mode 100644 index 00000000..521ca3d2 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/DisCalCommand.java @@ -0,0 +1,359 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.Main; +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.object.BotSettings; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.api.utils.GeneralUtils; +import com.cloudcraftgaming.discal.api.utils.PermissionChecker; +import com.cloudcraftgaming.discal.bot.utils.ChannelUtils; +import com.cloudcraftgaming.discal.bot.utils.RoleUtils; +import com.cloudcraftgaming.discal.web.handler.DiscordAccountHandler; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IRole; +import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.EmbedBuilder; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/5/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class DisCalCommand implements ICommand { + + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "Discal"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + return new ArrayList<>(); + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("event"); + info.setDescription("Used to configure DisCal"); + info.setExample("!DisCal (function) (value)"); + + info.getSubCommands().put("settings", "Displays the bot's settings."); + info.getSubCommands().put("role", "Sets the control role for the bot."); + info.getSubCommands().put("channel", "Sets the channel bot commands can be used in."); + info.getSubCommands().put("simpleannouncement", "Removes \"Advanced\" info from announcements."); + info.getSubCommands().put("dmannouncement", "Allows the bot to DM a user an announcement."); + info.getSubCommands().put("dmannouncements", "Alias for \"dmAnnouncement\""); + info.getSubCommands().put("language", "Sets the bot's language."); + info.getSubCommands().put("lang", "Sets the bot's language."); + info.getSubCommands().put("prefix", "Sets the bot's prefix."); + info.getSubCommands().put("invite", "Displays an invite to the support guild."); + info.getSubCommands().put("dashboard", "Displays the link to the web control dashboard."); + info.getSubCommands().put("brand", "Enables/Disables server branding."); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length < 1) { + moduleDisCalInfo(event, settings); + } else { + switch (args[0].toLowerCase()) { + case "discal": + moduleDisCalInfo(event, settings); + break; + case "settings": + moduleSettings(event, settings); + break; + case "role": + moduleControlRole(args, event, settings); + break; + case "channel": + moduleDisCalChannel(args, event, settings); + break; + case "simpleannouncement": + moduleSimpleAnnouncement(event, settings); + break; + case "dmannouncement": + moduleDmAnnouncements(event, settings); + break; + case "dmannouncements": + moduleDmAnnouncements(event, settings); + break; + case "language": + moduleLanguage(args, event, settings); + break; + case "lang": + moduleLanguage(args, event, settings); + break; + case "prefix": + modulePrefix(args, event, settings); + break; + case "invite": + moduleInvite(event, settings); + break; + case "dashboard": + moduleDashboard(event, settings); + break; + case "brand": + moduleBrand(event, settings); + break; + default: + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Invalid", settings), event); + break; + } + } + return false; + } + + private void moduleDisCalInfo(MessageReceivedEvent event, GuildSettings settings) { + IGuild guild = event.getGuild(); + + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal!"); + em.withTitle(MessageManager.getMessage("Embed.DisCal.Info.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.Developer", settings), "NovaFox161", true); + em.appendField(MessageManager.getMessage("Embed.Discal.Info.Version", settings), Main.version, true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.Library", settings), "Discord4J, version 2.9.2", false); + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.TotalGuilds", settings), DisCalAPI.getAPI().getClient().getGuilds().size() + "", true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.TotalCalendars", settings), DatabaseManager.getManager().getCalendarCount() + "", true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.TotalAnnouncements", settings), DatabaseManager.getManager().getAnnouncementCount() + "", true); + if (BotSettings.RUN_API.get().equalsIgnoreCase("True")) { + //TODO: Add to translations + em.appendField("Users in Dashboard", DiscordAccountHandler.getHandler().accountCount() + "", true); + } + em.appendField(MessageManager.getMessage("Embed.DisCal.Info.Ping", "%shard%", (guild.getShard().getInfo()[0] + 1) + "/" + DisCalAPI.getAPI().getClient().getShardCount(), settings), guild.getShard().getResponseTime() + "ms", false); + em.withFooterText(MessageManager.getMessage("Embed.DisCal.Info.Patron", settings) + ": https://www.patreon.com/Novafox"); + em.withUrl("https://www.discalbot.com"); + em.withColor(56, 138, 237); + MessageManager.sendMessage(em.build(), event); + } + + /** + * Sets the control role for the guild. + * + * @param args The args of the command. + * @param event The event received. + */ + private void moduleControlRole(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (PermissionChecker.hasSufficientRole(event)) { + if (args.length > 1) { + String roleName = GeneralUtils.getContent(args, 1); + IRole controlRole; + + if (!"everyone".equalsIgnoreCase(roleName)) { + controlRole = RoleUtils.getRoleFromID(roleName, event); + + if (controlRole != null) { + settings.setControlRole(controlRole.getStringID()); + DatabaseManager.getManager().updateSettings(settings); + //Send message. + MessageManager.sendMessage(MessageManager.getMessage("DisCal.ControlRole.Set", "%role%", controlRole.getName(), settings), event); + + } else { + //Invalid role. + MessageManager.sendMessage(MessageManager.getMessage("DisCal.ControlRole.Invalid", settings), event); + } + } else { + //Role is @everyone, set this so that anyone can control the bot. + settings.setControlRole("everyone"); + DatabaseManager.getManager().updateSettings(settings); + //Send message + MessageManager.sendMessage(MessageManager.getMessage("DisCal.ControlRole.Reset", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("DisCal.ControlRole.Specify", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + } + } + + /** + * Sets the channel for the guild that DisCal can respond in. + * + * @param args The command args + * @param event The event received. + */ + private void moduleDisCalChannel(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String channelName = args[1]; + if (channelName.equalsIgnoreCase("all")) { + //Reset channel info. + settings.setDiscalChannel("all"); + DatabaseManager.getManager().updateSettings(settings); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Channel.All", settings), event); + } else { + if (ChannelUtils.channelExists(channelName, event)) { + IChannel channel = ChannelUtils.getChannelFromNameOrId(channelName, event); + if (channel != null) { + settings.setDiscalChannel(channel.getStringID()); + DatabaseManager.getManager().updateSettings(settings); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Channel.Set", "%channel%", channel.getName(), settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Discal.Channel.NotFound", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Discal.Channel.NotFound", settings), event); + } + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Channel.Specify", settings), event); + } + } + + private void moduleSimpleAnnouncement(MessageReceivedEvent event, GuildSettings settings) { + settings.setSimpleAnnouncements(!settings.usingSimpleAnnouncements()); + DatabaseManager.getManager().updateSettings(settings); + + MessageManager.sendMessage(MessageManager.getMessage("DisCal.SimpleAnnouncement", "%value%", settings.usingSimpleAnnouncements() + "", settings), event); + } + + private void moduleSettings(MessageReceivedEvent event, GuildSettings settings) { + long guildId = event.getGuild().getLongID(); + + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.DisCal.Settings.Title", settings)); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.ExternalCal", settings), String.valueOf(settings.useExternalCalendar()), true); + if (RoleUtils.roleExists(settings.getControlRole(), event)) { + em.appendField(MessageManager.getMessage("Embed.Discal.Settings.Role", settings), RoleUtils.getRoleNameFromID(settings.getControlRole(), event), true); + } else { + em.appendField(MessageManager.getMessage("Embed.Discal.Settings.Role", settings), "everyone", true); + } + if (ChannelUtils.channelExists(settings.getDiscalChannel(), event)) { + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Channel", settings), ChannelUtils.getChannelNameFromNameOrId(settings.getDiscalChannel(), guildId), false); + } else { + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Channel", settings), "All Channels", true); + } + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.SimpleAnn", settings), String.valueOf(settings.usingSimpleAnnouncements()), true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Patron", settings), String.valueOf(settings.isPatronGuild()), true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Dev", settings), String.valueOf(settings.isDevGuild()), true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.MaxCal", settings), String.valueOf(settings.getMaxCalendars()), true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Language", settings), settings.getLang(), true); + em.appendField(MessageManager.getMessage("Embed.DisCal.Settings.Prefix", settings), settings.getPrefix(), true); + //TODO: Add translations... + em.appendField("Using Branding", settings.isBranded() + "", true); + em.withFooterText(MessageManager.getMessage("Embed.DisCal.Info.Patron", settings) + ": https://www.patreon.com/Novafox"); + em.withUrl("https://www.discalbot.com/"); + em.withColor(56, 138, 237); + MessageManager.sendMessage(em.build(), event); + } + + private void moduleDmAnnouncements(MessageReceivedEvent event, GuildSettings settings) { + if (settings.isDevGuild()) { + IUser user = event.getAuthor(); + + if (settings.getDmAnnouncements().contains(user.getStringID())) { + settings.getDmAnnouncements().remove(user.getStringID()); + DatabaseManager.getManager().updateSettings(settings); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.DmAnnouncements.Off", settings), event); + } else { + settings.getDmAnnouncements().add(user.getStringID()); + DatabaseManager.getManager().updateSettings(settings); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.DmAnnouncements.On", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Disabled", settings), event); + } + } + + private void modulePrefix(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (PermissionChecker.hasManageServerRole(event)) { + if (args.length == 2) { + String prefix = args[1]; + + settings.setPrefix(prefix); + DatabaseManager.getManager().updateSettings(settings); + + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Prefix.Set", "%prefix%", prefix, settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Prefix.Specify", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.MANAGE_SERVER", settings), event); + } + } + + private void moduleLanguage(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (PermissionChecker.hasManageServerRole(event)) { + if (args.length == 2) { + String value = args[1]; + if (MessageManager.isSupported(value)) { + String valid = MessageManager.getValidLang(value); + + settings.setLang(valid); + DatabaseManager.getManager().updateSettings(settings); + + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Lang.Success", settings), event); + } else { + String langs = MessageManager.getLangs().toString().replace("[", "").replace("]", ""); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Lang.Unsupported", "%values%", langs, settings), event); + } + } else { + String langs = MessageManager.getLangs().toString().replace("[", "").replace("]", ""); + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Lang.Specify", "%values%", langs, settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.MANAGE_SERVER", settings), event); + } + } + + private void moduleInvite(MessageReceivedEvent event, GuildSettings settings) { + String INVITE_LINK = "https://discord.gg/2TFqyuy"; + MessageManager.sendMessage(MessageManager.getMessage("DisCal.InviteLink", "%link%", INVITE_LINK, settings), event); + } + + private void moduleBrand(MessageReceivedEvent event, GuildSettings settings) { + if (PermissionChecker.hasSufficientRole(event)) { + if (settings.isPatronGuild()) { + settings.setBranded(!settings.isBranded()); + DatabaseManager.getManager().updateSettings(settings); + + MessageManager.sendMessage(MessageManager.getMessage("DisCal.Brand", "%value%", settings.isBranded() + "", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Patron", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Perm.CONTROL_ROLE", settings), event); + } + } + + private void moduleDashboard(MessageReceivedEvent event, GuildSettings settings) { + String DASHBOARD_LINK = "https://www.discalbot.com/dashboard"; + MessageManager.sendMessage(MessageManager.getMessage("DisCal.DashboardLink", "%link%", DASHBOARD_LINK, settings), event); + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventCommand.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventCommand.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventCommand.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventListCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventListCommand.java new file mode 100644 index 00000000..879fd42c --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/EventListCommand.java @@ -0,0 +1,211 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.bot.internal.calendar.event.EventMessageFormatter; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.client.util.DateTime; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; +import com.google.api.services.calendar.model.Events; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class EventListCommand implements ICommand { + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "events"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + return new ArrayList<>(); + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("events"); + info.setDescription("Lists the specified amount of events from the guild calendar."); + info.setExample("!events (number or function) (other args if applicable)"); + + info.getSubCommands().put("search", "Searches for events based on specific criteria rather than just the next upcoming events"); + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + //Get events from calendar + if (args.length < 1) { + moduleSimpleList(args, event, settings); + } else { + switch (args[0].toLowerCase()) { + case "search": + if (settings.isDevGuild()) + moduleSearch(args, event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Disabled", settings), event); + break; + case "today": + if (settings.isDevGuild()) + moduleDay(args, event, settings); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Disabled", settings), event); + break; + default: + moduleSimpleList(args, event, settings); + break; + } + } + return false; + } + + @SuppressWarnings("Duplicates") + private void moduleSimpleList(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 0) { + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + DateTime now = new DateTime(System.currentTimeMillis()); + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(event.getGuild().getLongID()); + Events events = service.events().list(calendarData.getCalendarAddress()) + .setMaxResults(1) + .setTimeMin(now) + .setOrderBy("startTime") + .setSingleEvents(true) + .setShowDeleted(false) + .execute(); + List items = events.getItems(); + if (items.size() == 0) { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Found.None", settings), event); + } else if (items.size() == 1) { + MessageManager.sendMessage(EventMessageFormatter.getEventEmbed(items.get(0), settings), MessageManager.getMessage("Event.List.Found.One", settings), event); + } + } catch (Exception e) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), event); + Logger.getLogger().exception(event.getAuthor(), "Failed to list events.", e, this.getClass(), true); + e.printStackTrace(); + } + } else if (args.length == 1) { + try { + Integer eventNum = Integer.valueOf(args[0]); + if (eventNum > 15) { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Amount.Over", settings), event); + return; + } + if (eventNum < 1) { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Amount.Under", settings), event); + return; + } + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + DateTime now = new DateTime(System.currentTimeMillis()); + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(event.getGuild().getLongID()); + Events events = service.events().list(calendarData.getCalendarAddress()) + .setMaxResults(eventNum) + .setTimeMin(now) + .setOrderBy("startTime") + .setSingleEvents(true) + .execute(); + List items = events.getItems(); + if (items.size() == 0) { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Found.None", settings), event); + } else if (items.size() == 1) { + MessageManager.sendMessage(EventMessageFormatter.getEventEmbed(items.get(0), settings), MessageManager.getMessage("Event.List.Found.One", settings), event); + } else { + //List events by Id only. + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Found.Many", "%amount%", items.size() + "", settings), event); + for (Event e: items) { + MessageManager.sendMessage(EventMessageFormatter.getCondensedEventEmbed(e, settings), event); + } + } + } catch (Exception e) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), event); + Logger.getLogger().exception(event.getAuthor(), "Failed to list events.", e, this.getClass(), true); + e.printStackTrace(); + } + } catch (NumberFormatException e) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Value.Integer", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Args.Many", settings), event); + } + } + + private void moduleSearch(String[] args, MessageReceivedEvent event, GuildSettings settings) { + + } + + @SuppressWarnings("Duplicates") + private void moduleDay(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 1) { + //Get the upcoming events in the next 24 hours. + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + DateTime now = new DateTime(System.currentTimeMillis()); + DateTime twentyFourHoursFromNow = new DateTime(now.getValue() + 86400000L); + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(event.getGuild().getLongID()); + Events events = service.events().list(calendarData.getCalendarAddress()) + .setMaxResults(20) + .setTimeMin(now) + .setTimeMax(twentyFourHoursFromNow) + .setOrderBy("startTime") + .setSingleEvents(true) + .setShowDeleted(false) + .execute(); + List items = events.getItems(); + if (items.size() == 0) { + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Found.None", settings), event); + } else if (items.size() == 1) { + MessageManager.sendMessage(EventMessageFormatter.getEventEmbed(items.get(0), settings), MessageManager.getMessage("Event.List.Found.One", settings), event); + } else { + //List events by Id only. + MessageManager.sendMessage(MessageManager.getMessage("Event.List.Found.Many", "%amount%", items.size() + "", settings), event); + for (Event e: items) { + MessageManager.sendMessage(EventMessageFormatter.getCondensedEventEmbed(e, settings), event); + } + } + } catch (Exception e) { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), event); + Logger.getLogger().exception(event.getAuthor(), "Failed to list events.", e, this.getClass(), true); + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/HelpCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/HelpCommand.java new file mode 100644 index 00000000..541041e0 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/HelpCommand.java @@ -0,0 +1,144 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.util.EmbedBuilder; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class HelpCommand implements ICommand { + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "help"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + return new ArrayList<>(); + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("help"); + info.setDescription("Displays help (duh)."); + info.setExample("!help (command) (sub-command)"); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length < 1) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle("DisCal Command Help"); + for (ICommand c: CommandExecutor.getExecutor().getCommands()) { + if (c.getAliases().size() > 0) { + String al = c.getAliases().toString(); + em.appendField(c.getCommand() + " " + al, c.getCommandInfo().getDescription(), true); + } else { + em.appendField(c.getCommand(), c.getCommandInfo().getDescription(), true); + } + } + em.withFooterText("Check out the official site for more command info!"); + em.withUrl("https://www.discalbot.com/commands"); + em.withColor(56, 138, 237); + MessageManager.sendMessage(em.build(), event); + } else if (args.length == 1) { + String cmdFor = args[0]; + ICommand cmd = CommandExecutor.getExecutor().getCommand(cmdFor); + if (cmd != null) + MessageManager.sendMessage(getCommandInfoEmbed(cmd), event); + + } else if (args.length == 2) { + //Display sub command info + String cmdFor = args[0]; + ICommand cmd = CommandExecutor.getExecutor().getCommand(cmdFor); + if (cmd != null) { + if (cmd.getCommandInfo().getSubCommands().containsKey(args[1].toLowerCase())) + MessageManager.sendMessage(getSubCommandEmbed(cmd, args[1].toLowerCase()), event); + else + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.InvalidSubCmd", settings), event); + } + } + + return false; + } + + //Embed formatters + private EmbedObject getCommandInfoEmbed(ICommand cmd) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.appendField("Command", cmd.getCommand(), true); + em.appendField("Description", cmd.getCommandInfo().getDescription(), true); + em.appendField("Example", cmd.getCommandInfo().getExample(), true); + + //Loop through sub commands + if (cmd.getCommandInfo().getSubCommands().size() > 0) { + String subs = cmd.getCommandInfo().getSubCommands().keySet().toString(); + subs = subs.replace("[", "").replace("]", ""); + em.appendField("Sub-Commands", subs, false); + } + + em.withFooterText("<> = required | () = optional"); + + em.withUrl("https://www.discalbot.com/commands"); + + em.withColor(56, 138, 237); + + return em.build(); + } + + private EmbedObject getSubCommandEmbed(ICommand cmd, String subCommand) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.appendField("Command", cmd.getCommand(), true); + em.appendField("Sub Command", subCommand, true); + + em.appendField("Usage", cmd.getCommandInfo().getSubCommands().get(subCommand), false); + + em.withFooterText("<> = required | () = optional"); + + em.withUrl("https://www.discalbot.com/commands"); + + em.withColor(56, 138, 237); + + return em.build(); + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/ICommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/ICommand.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/ICommand.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/command/ICommand.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/LinkCalendarCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/LinkCalendarCommand.java new file mode 100644 index 00000000..826a9f8e --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/LinkCalendarCommand.java @@ -0,0 +1,89 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.message.calendar.CalendarMessageFormatter; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.logger.Logger; +import com.google.api.services.calendar.model.Calendar; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 1/3/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class LinkCalendarCommand implements ICommand { + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "LinkCalendar"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + ArrayList aliases = new ArrayList<>(); + aliases.add("linkcal"); + aliases.add("calendarlink"); + aliases.add("callink"); + aliases.add("linkcallador"); + return aliases; + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("linkCalendar"); + info.setDescription("Links the guild's calendar in a pretty embed!"); + info.setExample("!linkCalendar"); + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + try { + //TODO: Handle multiple calendars... + CalendarData data = DatabaseManager.getManager().getMainCalendar(event.getGuild().getLongID()); + + if (data.getCalendarAddress().equalsIgnoreCase("primary")) { + //Does not have a calendar. + MessageManager.sendMessage(MessageManager.getMessage("Creator.Calendar.NoCalendar", settings), event); + } else { + Calendar cal = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute(); + + MessageManager.sendMessage(CalendarMessageFormatter.getCalendarLinkEmbed(cal, settings), event); + } + } catch (Exception e) { + Logger.getLogger().exception(event.getAuthor(), "Failed to connect to Google Cal.", e, this.getClass(), true); + MessageManager.sendMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), event); + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/module/command/RsvpCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/RsvpCommand.java new file mode 100644 index 00000000..13dfeee8 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/RsvpCommand.java @@ -0,0 +1,284 @@ +package com.cloudcraftgaming.discal.bot.module.command; + +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.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.command.CommandInfo; +import com.cloudcraftgaming.discal.api.object.event.RsvpData; +import com.cloudcraftgaming.discal.api.utils.EventUtils; +import com.cloudcraftgaming.discal.api.utils.TimeUtils; +import com.cloudcraftgaming.discal.bot.utils.UserUtils; +import sx.blah.discord.api.internal.json.objects.EmbedObject; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.EmbedBuilder; + +import java.util.ArrayList; + +/** + * Created by Nova Fox on 8/31/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class RsvpCommand implements ICommand { + /** + * Gets the command this Object is responsible for. + * + * @return The command this Object is responsible for. + */ + @Override + public String getCommand() { + return "rsvp"; + } + + /** + * Gets the short aliases of the command this object is responsible for. + *
+ * This will return an empty ArrayList if none are present + * + * @return The aliases of the command. + */ + @Override + public ArrayList getAliases() { + return new ArrayList<>(); + } + + /** + * Gets the info on the command (not sub command) to be used in help menus. + * + * @return The command info. + */ + @Override + public CommandInfo getCommandInfo() { + CommandInfo info = new CommandInfo("rsvp"); + info.setDescription("Confirms attendance to an event"); + info.setExample("!rsvp "); + + info.getSubCommands().put("onTime", "Marks you are going to event"); + info.getSubCommands().put("late", "Marks that you will be late to event"); + info.getSubCommands().put("not", "Marks that you are NOT going to event"); + info.getSubCommands().put("unsure", "Marks that you may or may not go to event"); + info.getSubCommands().put("remove", "Removes your RSVP from the event"); + info.getSubCommands().put("list", "Lists who has RSVPed to event"); + + return info; + } + + /** + * Issues the command this Object is responsible for. + * + * @param args The command arguments. + * @param event The event received. + * @return true if successful, else false. + */ + @Override + public boolean issueCommand(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length > 0) { + switch (args[0].toLowerCase()) { + case "ontime": + moduleGoing(args, event, settings); + break; + case "late": + moduleGoingLate(args, event, settings); + break; + case "not": + moduleNotGoing(args, event, settings); + break; + case "unsure": + moduleUnsure(args, event, settings); + break; + case "remove": + moduleRemove(args, event, settings); + break; + case "list": + moduleList(args, event, settings); + break; + default: + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.InvalidSubCmd", settings), event); + break; + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notification.Args.Few", settings), event); + } + return false; + } + + private void moduleGoing(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + if (!TimeUtils.inPast(eventId, settings)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + data.removeCompletely(event.getAuthor().getStringID()); + data.getGoingOnTime().add(event.getAuthor().getStringID()); + + DatabaseManager.getManager().updateRsvpData(data); + MessageManager.sendMessage(getRsvpEmbed(data, settings), MessageManager.getMessage("RSVP.going.success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.InPast", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NotExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.going.specify", settings), event); + } + } + + private void moduleGoingLate(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + if (!TimeUtils.inPast(eventId, settings)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + data.removeCompletely(event.getAuthor().getStringID()); + data.getGoingLate().add(event.getAuthor().getStringID()); + + DatabaseManager.getManager().updateRsvpData(data); + MessageManager.sendMessage(getRsvpEmbed(data, settings), MessageManager.getMessage("RSVP.late.success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.InPast", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NotExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.late.specify", settings), event); + } + } + + private void moduleNotGoing(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + if (!TimeUtils.inPast(eventId, settings)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + data.removeCompletely(event.getAuthor().getStringID()); + data.getNotGoing().add(event.getAuthor().getStringID()); + + DatabaseManager.getManager().updateRsvpData(data); + MessageManager.sendMessage(getRsvpEmbed(data, settings), MessageManager.getMessage("RSVP.not.success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.InPast", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NotExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.not.specify", settings), event); + } + } + + private void moduleRemove(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + if (!TimeUtils.inPast(eventId, settings)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + data.removeCompletely(event.getAuthor().getStringID()); + + DatabaseManager.getManager().updateRsvpData(data); + MessageManager.sendMessage(getRsvpEmbed(data, settings), MessageManager.getMessage("RSVP.remove.success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.InPast", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NotExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.remove.specify", settings), event); + } + } + + private void moduleUnsure(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + if (!TimeUtils.inPast(eventId, settings)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + data.removeCompletely(event.getAuthor().getStringID()); + data.getUndecided().add(event.getAuthor().getStringID()); + + DatabaseManager.getManager().updateRsvpData(data); + MessageManager.sendMessage(getRsvpEmbed(data, settings), MessageManager.getMessage("RSVP.unsure.success", settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.InPast", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NotExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.unsure.specify", settings), event); + } + } + + private void moduleList(String[] args, MessageReceivedEvent event, GuildSettings settings) { + if (args.length == 2) { + String eventId = args[1]; + if (EventUtils.eventExists(settings, eventId)) { + RsvpData data = DatabaseManager.getManager().getRsvpData(settings.getGuildID(), eventId); + + MessageManager.sendMessage(getRsvpEmbed(data, settings), event); + } else { + MessageManager.sendMessage(MessageManager.getMessage("Notifications.Event.NoExist", settings), event); + } + } else { + MessageManager.sendMessage(MessageManager.getMessage("RSVP.list.specify", settings), event); + } + } + + + private EmbedObject getRsvpEmbed(RsvpData data, GuildSettings settings) { + EmbedBuilder em = new EmbedBuilder(); + em.withAuthorIcon(DisCalAPI.getAPI().iconUrl); + em.withAuthorName("DisCal"); + em.withTitle(MessageManager.getMessage("Embed.RSVP.List.Title", settings)); + em.appendField("Event ID", data.getEventId(), false); + + IGuild g = DisCalAPI.getAPI().getClient().getGuildByID(settings.getGuildID()); + + StringBuilder onTime = new StringBuilder(); + for (IUser u: UserUtils.getUsers(data.getGoingOnTime(), g)) { + onTime.append(u.getName()).append(", "); + } + StringBuilder late = new StringBuilder(); + for (IUser u: UserUtils.getUsers(data.getGoingLate(), g)) { + late.append(u.getName()).append(", "); + } + StringBuilder unsure = new StringBuilder(); + for (IUser u: UserUtils.getUsers(data.getUndecided(), g)) { + unsure.append(u.getName()).append(", "); + } + StringBuilder notGoing = new StringBuilder(); + for (IUser u: UserUtils.getUsers(data.getNotGoing(), g)) { + notGoing.append(u.getName()).append(", "); + } + + if (onTime.toString().isEmpty()) + em.appendField("On time", "N/a", true); + else + em.appendField("On Time", onTime.toString(), true); + + if (late.toString().isEmpty()) + em.appendField("Late", "N/a", true); + else + em.appendField("Late", late.toString(), true); + + if (unsure.toString().isEmpty()) + em.appendField("Unsure", "N/a", true); + else + em.appendField("Unsure", unsure.toString(), true); + + if (notGoing.toString().isEmpty()) + em.appendField("Not Going", "N/a", true); + else + em.appendField("Not Going", notGoing.toString(), true); + + em.withFooterText(MessageManager.getMessage("Embed.RSVP.List.Footer", settings)); + em.withColor(56, 138, 237); + + return em.build(); + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/TimeCommand.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/command/TimeCommand.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/command/TimeCommand.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/command/TimeCommand.java diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/misc/StatusChanger.java b/src/main/java/com/cloudcraftgaming/discal/bot/module/misc/StatusChanger.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/module/misc/StatusChanger.java rename to src/main/java/com/cloudcraftgaming/discal/bot/module/misc/StatusChanger.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/utils/ChannelUtils.java b/src/main/java/com/cloudcraftgaming/discal/bot/utils/ChannelUtils.java new file mode 100644 index 00000000..06da4690 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/utils/ChannelUtils.java @@ -0,0 +1,87 @@ +package com.cloudcraftgaming.discal.bot.utils; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; + +/** + * Created by Nova Fox on 3/29/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class ChannelUtils { + /** + * Checks if the specified channel exists. + * + * @param nameOrId The channel name or ID. + * @param event The event received. + * @return true if exists, else false. + */ + public static boolean channelExists(String nameOrId, MessageReceivedEvent event) { + if (nameOrId.contains("#")) + nameOrId = nameOrId.replace("#", ""); + + for (IChannel c: event.getGuild().getChannels()) { + if (c.getName().equalsIgnoreCase(nameOrId) || c.getStringID().equals(nameOrId)) + return true; + } + return false; + } + + /** + * Gets the IChannel from its name. + * + * @param nameOrId The channel name or ID. + * @param event The event received. + * @return the IChannel if successful, else null. + */ + public static IChannel getChannelFromNameOrId(String nameOrId, MessageReceivedEvent event) { + if (nameOrId.contains("#")) + nameOrId = nameOrId.replace("#", ""); + + for (IChannel c: event.getGuild().getChannels()) { + if (c.getName().equalsIgnoreCase(nameOrId) || c.getStringID().equals(nameOrId)) + return c; + } + return null; + } + + /** + * Gets the IChannel from its name. + * + * @param nameOrId The channel name or ID. + * @param guildId The ID of the guild this channel belongs to. + * @return the IChannel if successful, else null. + */ + public static IChannel getChannelFromNameOrId(String nameOrId, long guildId) { + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(guildId); + if (nameOrId.contains("#")) + nameOrId = nameOrId.replace("#", ""); + + for (IChannel c: guild.getChannels()) { + if (c.getName().equalsIgnoreCase(nameOrId) || c.getStringID().equals(nameOrId)) + return c; + } + return null; + } + + /** + * Gets the IChannel from its name. + * + * @param nameOrId The channel name or ID. + * @param guildId The ID of the guild this channel belongs to. + * @return the IChannel if successful, else null. + */ + public static String getChannelNameFromNameOrId(String nameOrId, long guildId) { + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(guildId); + if (nameOrId.contains("#")) + nameOrId = nameOrId.replace("#", ""); + + for (IChannel c: guild.getChannels()) { + if (c.getName().equalsIgnoreCase(nameOrId) || c.getStringID().equals(nameOrId)) + return c.getName(); + } + return "ERROR"; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/utils/GuildUtils.java b/src/main/java/com/cloudcraftgaming/discal/bot/utils/GuildUtils.java new file mode 100644 index 00000000..bdd98b17 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/utils/GuildUtils.java @@ -0,0 +1,13 @@ +package com.cloudcraftgaming.discal.bot.utils; + +/** + * Created by Nova Fox on 11/6/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class GuildUtils { + public static boolean active(long id) { + return true; + //return Main.client.getGuildByID(id) != null; + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/utils/RoleUtils.java b/src/main/java/com/cloudcraftgaming/discal/bot/utils/RoleUtils.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/utils/RoleUtils.java rename to src/main/java/com/cloudcraftgaming/discal/bot/utils/RoleUtils.java diff --git a/src/main/java/com/cloudcraftgaming/discal/bot/utils/TimeZoneUtils.java b/src/main/java/com/cloudcraftgaming/discal/bot/utils/TimeZoneUtils.java new file mode 100644 index 00000000..e165b357 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/bot/utils/TimeZoneUtils.java @@ -0,0 +1,29 @@ +package com.cloudcraftgaming.discal.bot.utils; + +import com.cloudcraftgaming.discal.api.enums.BadTimezone; +import org.joda.time.DateTimeZone; + +/** + * Created by Nova Fox on 4/7/2017. + * Website: www.cloudcraftgaming.com + * For Project: DisCal + */ +public class TimeZoneUtils { + public static boolean isValid(String value) { + try { + DateTimeZone tz = DateTimeZone.forID(value); + return tz != null && !isBadTz(value); + } catch (IllegalArgumentException e) { + return false; + } + } + + private static boolean isBadTz(String value) { + try { + BadTimezone.valueOf(value.replaceAll("/", "_")); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } +} \ No newline at end of file diff --git a/Bot/src/main/java/com/cloudcraftgaming/discal/bot/utils/UserUtils.java b/src/main/java/com/cloudcraftgaming/discal/bot/utils/UserUtils.java similarity index 100% rename from Bot/src/main/java/com/cloudcraftgaming/discal/bot/utils/UserUtils.java rename to src/main/java/com/cloudcraftgaming/discal/bot/utils/UserUtils.java diff --git a/src/main/java/com/cloudcraftgaming/discal/logger/Logger.java b/src/main/java/com/cloudcraftgaming/discal/logger/Logger.java new file mode 100644 index 00000000..e62044dc --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/logger/Logger.java @@ -0,0 +1,270 @@ +package com.cloudcraftgaming.discal.logger; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.message.MessageManager; +import com.cloudcraftgaming.discal.api.object.BotSettings; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IUser; +import sx.blah.discord.util.EmbedBuilder; + +import javax.annotation.Nullable; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +public class Logger { + private static Logger instance; + private String exceptionsFile; + private String apiFile; + private String announcementsFile; + private String debugFile; + + private Logger() { + } //Prevent initialization + + public static Logger getLogger() { + if (instance == null) + instance = new Logger(); + return instance; + } + + public void init() { + //Create files... + String timestamp = new SimpleDateFormat("dd-MM-yyyy-hh.mm.ss").format(System.currentTimeMillis()); + + exceptionsFile = BotSettings.LOG_FOLDER.get() + "/" + timestamp + "-exceptions.log"; + apiFile = BotSettings.LOG_FOLDER.get() + "/" + timestamp + "-api.log"; + announcementsFile = BotSettings.LOG_FOLDER.get() + "/" + timestamp + "-announcements.log"; + debugFile = BotSettings.LOG_FOLDER.get() + "/" + timestamp + "-debug.log"; + + try { + PrintWriter exceptions = new PrintWriter(exceptionsFile, "UTF-8"); + exceptions.println("INIT --- " + timestamp + " ---"); + exceptions.close(); + + PrintWriter api = new PrintWriter(apiFile, "UTF-8"); + api.println("INIT --- " + timestamp + " ---"); + api.close(); + + PrintWriter announcement = new PrintWriter(announcementsFile, "UTF-8"); + announcement.println("INIT --- " + timestamp + " ---"); + announcement.close(); + + PrintWriter debug = new PrintWriter(debugFile, "UTF-8"); + debug.println("INIT --- " + timestamp + " ---"); + debug.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void exception(@Nullable IUser author, @Nullable String message, Exception e, Class clazz, boolean post) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + String error = sw.toString(); // stack trace as a string + pw.close(); + try { + sw.close(); + } catch (IOException e1) { + //Can ignore silently... + } + + if (DisCalAPI.getAPI().getClient().getOurUser() != null && DisCalAPI.getAPI().getClient().isLoggedIn()) { + IUser bot = DisCalAPI.getAPI().getClient().getOurUser(); + + if (post) { + String shortError = error; + if (error.length() > 1250) + shortError = error.substring(0, 1250); + + + EmbedBuilder em = new EmbedBuilder(); + if (bot != null) + em.withAuthorIcon(bot.getAvatarURL()); + + if (author != null) { + em.withAuthorName(author.getName()); + em.withThumbnail(author.getAvatarURL()); + } + em.withColor(239, 15, 0); + em.withFooterText(clazz.getName()); + + //Send to discord! + em.appendField("Time", timeStamp, true); + if (e.getMessage() != null) { + if (e.getMessage().length() > 1024) + em.appendField("Exception", e.getMessage().substring(0, 1024), true); + else + em.appendField("Exception", e.getMessage(), true); + } + if (message != null) + em.appendField("Message", message, true); + + + //Get DisCal guild and channel.. + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(DisCalAPI.getAPI().serverId); + IChannel channel = guild.getChannelByID(DisCalAPI.getAPI().errorLog); + + MessageManager.sendMessage(em.build(), "```" + shortError + "```", channel); + } + } + + //ALWAYS LOG TO FILE! + try { + FileWriter exceptions = new FileWriter(exceptionsFile, true); + exceptions.write("ERROR --- " + timeStamp + " ---" + MessageManager.lineBreak); + if (author != null) + exceptions.write("user: " + author.getName() + "#" + author.getDiscriminator() + MessageManager.lineBreak); + + if (message != null) + exceptions.write("message: " + message + MessageManager.lineBreak); + + exceptions.write(error + MessageManager.lineBreak); + exceptions.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void debug(@Nullable IUser author, String message, @Nullable String info, Class clazz, boolean post) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + if (DisCalAPI.getAPI().getClient() != null) { + if (post) { + IUser bot = DisCalAPI.getAPI().getClient().getOurUser(); + EmbedBuilder em = new EmbedBuilder(); + assert bot != null; + em.withAuthorIcon(bot.getAvatarURL()); + if (author != null) { + em.withAuthorName(author.getName()); + em.withThumbnail(author.getAvatarURL()); + } + em.withColor(239, 15, 0); + em.withFooterText(clazz.getName()); + + + em.appendField("Time", timeStamp, true); + if (info != null) + em.appendField("Additional Info", info, true); + + + //Get DisCal guild and channel.. + IGuild guild = DisCalAPI.getAPI().getClient().getGuildByID(DisCalAPI.getAPI().serverId); + IChannel channel = guild.getChannelByID(DisCalAPI.getAPI().errorLog); + + MessageManager.sendMessage(em.build(), "```" + message + "```", channel); + } + } + + //ALWAYS LOG TO FILE! + try { + FileWriter file = new FileWriter(debugFile, true); + file.write("DEBUG --- " + timeStamp + " ---" + MessageManager.lineBreak); + if (author != null) + file.write("user: " + author.getName() + "#" + author.getDiscriminator() + MessageManager.lineBreak); + + if (message != null) + file.write("message: " + message + MessageManager.lineBreak); + + if (info != null) + file.write("info: " + info + MessageManager.lineBreak); + + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void debug(String message) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(debugFile, true); + file.write("DEBUG --- " + timeStamp + " ---" + MessageManager.lineBreak); + if (message != null) + file.write("info: " + message + MessageManager.lineBreak); + + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void api(String message) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(apiFile, true); + file.write("API --- " + timeStamp + " ---" + MessageManager.lineBreak); + file.write("info: " + message + MessageManager.lineBreak); + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void api(String message, String ip) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(apiFile, true); + file.write("API --- " + timeStamp + " ---" + MessageManager.lineBreak); + file.write("info: " + message + MessageManager.lineBreak); + file.write("IP: " + ip + MessageManager.lineBreak); + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void api(String message, String ip, String host, String endpoint) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(apiFile, true); + file.write("API --- " + timeStamp + " ---" + MessageManager.lineBreak); + file.write("info: " + message + MessageManager.lineBreak); + file.write("IP: " + ip + MessageManager.lineBreak); + file.write("Host: " + host + MessageManager.lineBreak); + file.write("Endpoint: " + endpoint + MessageManager.lineBreak); + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void announcement(String message) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(announcementsFile, true); + file.write("ANNOUNCEMENT --- " + timeStamp + " ---" + MessageManager.lineBreak); + file.write("info: " + message + MessageManager.lineBreak); + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } + + public void announcement(String message, String guildId, String announcementId, String eventId) { + String timeStamp = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(Calendar.getInstance().getTime()); + + try { + FileWriter file = new FileWriter(announcementsFile, true); + file.write("ANNOUNCEMENT --- " + timeStamp + " ---" + MessageManager.lineBreak); + file.write("info: " + message + MessageManager.lineBreak); + file.write("guild Id: " + guildId + MessageManager.lineBreak); + file.write("announcement Id: " + announcementId + MessageManager.lineBreak); + file.write("event id: " + eventId + MessageManager.lineBreak); + file.close(); + } catch (IOException io) { + io.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/AnnouncementEndpoint.java b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/AnnouncementEndpoint.java new file mode 100644 index 00000000..5c28f057 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/AnnouncementEndpoint.java @@ -0,0 +1,268 @@ +package com.cloudcraftgaming.discal.web.endpoints.v1; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.announcement.AnnouncementType; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.object.announcement.Announcement; +import com.cloudcraftgaming.discal.logger.Logger; +import com.cloudcraftgaming.discal.web.utils.ResponseUtils; +import org.json.JSONException; +import org.json.JSONObject; +import spark.Request; +import spark.Response; + +import java.util.ArrayList; +import java.util.UUID; + +import static spark.Spark.halt; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +@SuppressWarnings("ThrowableNotThrown") +public class AnnouncementEndpoint { + public static String getAnnouncement(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + Long guildId = jsonMain.getLong("guild_id"); + String announcementId = jsonMain.getString("id"); + + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementId), guildId); + + if (a != null) { + + response.type("application/json"); + response.status(200); + + JSONObject body = new JSONObject(); + body.put("channel", a.getAnnouncementChannelId()); + body.put("event_id", a.getEventId()); + body.put("event_color", a.getEventColor().name()); + body.put("type", a.getAnnouncementType().name()); + body.put("hours", a.getHoursBefore()); + body.put("minutes", a.getMinutesBefore()); + body.put("info", a.getInfo()); + body.put("enabled", a.isEnabled()); + body.put("info_only", a.isInfoOnly()); + body.put("subscribers_role", a.getSubscriberRoleIds()); + body.put("subscribers_user", a.getSubscriberUserIds()); + + response.body(body.toString()); + } else { + response.type("application/json"); + response.status(404); + response.body(ResponseUtils.getJsonResponseMessage("Announcement not found.")); + } + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal get announcement error", e, AnnouncementEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } + + public static String createAnnouncement(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + Long guildId = jsonMain.getLong("guild_id"); + + Announcement a = new Announcement(guildId); + + JSONObject body = new JSONObject(request.body()); + a.setAnnouncementChannelId(body.getString("channel")); + a.setAnnouncementType(AnnouncementType.fromValue(body.getString("type"))); + + if (a.getAnnouncementType().equals(AnnouncementType.COLOR)) + a.setEventColor(EventColor.fromNameOrHexOrID(body.getString("event_color"))); + + if (a.getAnnouncementType().equals(AnnouncementType.RECUR) || a.getAnnouncementType().equals(AnnouncementType.SPECIFIC)) + a.setEventId(body.getString("event_id")); + + + a.setHoursBefore(body.getInt("hours")); + a.setMinutesBefore(body.getInt("minutes")); + a.setInfo(body.getString("info")); + + if (DatabaseManager.getManager().updateAnnouncement(a)) { + response.type("application/json"); + response.status(200); + + JSONObject responseBody = new JSONObject(); + responseBody.put("Message", "Successfully created announcement"); + responseBody.put("id", a.getAnnouncementId().toString()); + response.body(responseBody.toString()); + } else { + response.type("application/json"); + response.status(500); + response.body(ResponseUtils.getJsonResponseMessage("Internal Server Error")); + } + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal create announcement error", e, AnnouncementEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } + + public static String updateAnnouncement(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + Long guildId = jsonMain.getLong("guild_id"); + String announcementId = jsonMain.getString("id"); + + Announcement a = DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementId), guildId); + + if (a != null) { + + JSONObject body = new JSONObject(request.body()); + + if (body.has("channel")) + a.setAnnouncementChannelId(body.getString("channel")); + if (body.has("event_id")) + a.setEventId(body.getString("event_id")); + if (body.has("event_color")) + a.setEventColor(EventColor.fromNameOrHexOrID(body.getString("event_color"))); + if (body.has("type")) + a.setAnnouncementType(AnnouncementType.fromValue(body.getString("type"))); + if (body.has("hours")) + a.setHoursBefore(body.getInt("hours")); + if (body.has("minutes")) + a.setMinutesBefore(body.getInt("minutes")); + if (body.has("info")) + a.setInfo(body.getString("info")); + if (body.has("enabled")) + a.setEnabled(body.getBoolean("enabled")); + if (body.has("info_only")) { + a.setInfoOnly(body.getBoolean("info_only")); + } + + if (DatabaseManager.getManager().updateAnnouncement(a)) { + response.type("application/json"); + response.status(200); + response.body(ResponseUtils.getJsonResponseMessage("Successfully updated announcement")); + } else { + response.type("application/json"); + response.status(500); + response.body(ResponseUtils.getJsonResponseMessage("Internal Server Error")); + } + } else { + response.type("application/json"); + response.status(404); + response.body(ResponseUtils.getJsonResponseMessage("Announcement not found")); + } + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal update announcement error", e, AnnouncementEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } + + public static String deleteAnnouncement(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + long guildId = jsonMain.getLong("guild_id"); + String announcementId = jsonMain.getString("id"); + + if (DatabaseManager.getManager().getAnnouncement(UUID.fromString(announcementId), guildId) != null) { + if (DatabaseManager.getManager().deleteAnnouncement(announcementId)) { + response.type("application/json"); + response.status(200); + response.body(ResponseUtils.getJsonResponseMessage("Successfully deleted announcement")); + } else { + response.type("application/json"); + response.status(500); + response.body(ResponseUtils.getJsonResponseMessage("Internal Server Error")); + } + } else { + response.type("application/json"); + response.status(404); + response.body(ResponseUtils.getJsonResponseMessage("Announcement not found")); + } + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal delete announcement error", e, AnnouncementEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } + + public static String listAnnouncements(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + long guildId = jsonMain.getLong("guild_id"); + + int amount = jsonMain.getInt("amount"); + + ArrayList announcements = new ArrayList<>(); + if (amount == -1) { + for (Announcement a: DatabaseManager.getManager().getAnnouncements(guildId)) { + JSONObject obj = new JSONObject(); + obj.put("id", a.getAnnouncementId().toString()); + obj.put("channel", a.getAnnouncementChannelId()); + obj.put("event_id", a.getEventId()); + obj.put("event_color", a.getEventColor().name()); + obj.put("type", a.getAnnouncementType().name()); + obj.put("hours", a.getHoursBefore()); + obj.put("minutes", a.getMinutesBefore()); + obj.put("info", a.getInfo()); + obj.put("enabled", a.isEnabled()); + obj.put("info_only", a.isInfoOnly()); + obj.put("subscribers_role", a.getSubscriberRoleIds()); + obj.put("subscribers_user", a.getSubscriberUserIds()); + + announcements.add(obj); + } + } else { + int i = 0; + for (Announcement a: DatabaseManager.getManager().getAnnouncements(guildId)) { + if (i < amount) { + JSONObject obj = new JSONObject(); + obj.put("id", a.getAnnouncementId().toString()); + obj.put("channel", a.getAnnouncementChannelId()); + obj.put("event_id", a.getEventId()); + obj.put("event_color", a.getEventColor().name()); + obj.put("type", a.getAnnouncementType().name()); + obj.put("hours", a.getHoursBefore()); + obj.put("minutes", a.getMinutesBefore()); + obj.put("info", a.getInfo()); + obj.put("enabled", a.isEnabled()); + obj.put("info_only", a.isInfoOnly()); + obj.put("subscribers_role", a.getSubscriberRoleIds()); + obj.put("subscribers_user", a.getSubscriberUserIds()); + + announcements.add(obj); + i++; + } else { + break; + } + } + } + + JSONObject body = new JSONObject(); + body.put("amount", announcements.size()); + body.put("announcements", announcements); + + response.type("application/json"); + response.status(200); + response.body(body.toString()); + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal list announcements error", e, AnnouncementEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/CalendarEndpoint.java b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/CalendarEndpoint.java new file mode 100644 index 00000000..f9873382 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/CalendarEndpoint.java @@ -0,0 +1,90 @@ +package com.cloudcraftgaming.discal.web.endpoints.v1; + +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.logger.Logger; +import com.cloudcraftgaming.discal.web.utils.ResponseUtils; +import org.json.JSONException; +import org.json.JSONObject; +import spark.Request; +import spark.Response; + +import java.util.ArrayList; + +import static spark.Spark.halt; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +@SuppressWarnings("ThrowableNotThrown") +public class CalendarEndpoint { + public static String getCalendar(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + Long guildId = jsonMain.getLong("guild_id"); + Integer calNumber = jsonMain.getInt("number"); + + CalendarData calendar = DatabaseManager.getManager().getCalendar(guildId, calNumber); + + if (!calendar.getCalendarAddress().equalsIgnoreCase("primary")) { + + JSONObject body = new JSONObject(); + body.put("external", calendar.isExternal()); + body.put("id", calendar.getCalendarId()); + body.put("address", calendar.getCalendarAddress()); + + response.type("application/json"); + response.status(200); + response.body(body.toString()); + } else { + response.type("application/json"); + response.status(404); + response.body(ResponseUtils.getJsonResponseMessage("Calendar not found")); + } + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal get calendar error", e, CalendarEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } + + public static String listCalendars(Request request, Response response) { + try { + JSONObject jsonMain = new JSONObject(request.body()); + long guildId = jsonMain.getLong("guild_id"); + + ArrayList cals = new ArrayList<>(); + for (CalendarData cal: DatabaseManager.getManager().getAllCalendars(guildId)) { + if (!cal.getCalendarAddress().equalsIgnoreCase("primary")) { + JSONObject body = new JSONObject(); + body.put("number", cal.getCalendarNumber()); + body.put("external", cal.isExternal()); + body.put("id", cal.getCalendarId()); + body.put("address", cal.getCalendarAddress()); + + cals.add(body); + } + } + + JSONObject body = new JSONObject(); + body.put("count", cals.size()); + body.put("calendars", cals); + + response.type("application/json"); + response.status(200); + response.body(body.toString()); + } catch (JSONException e) { + e.printStackTrace(); + halt(400, "Bad Request"); + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB-API] Internal list calendars error", e, CalendarEndpoint.class, true); + halt(500, "Internal Server Error"); + } + return response.body(); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/EventEndpoint.java b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/EventEndpoint.java new file mode 100644 index 00000000..25dbd525 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/EventEndpoint.java @@ -0,0 +1,404 @@ +package com.cloudcraftgaming.discal.web.endpoints.v1; + +import com.cloudcraftgaming.discal.api.calendar.CalendarAuth; +import com.cloudcraftgaming.discal.api.crypto.KeyGenerator; +import com.cloudcraftgaming.discal.api.database.DatabaseManager; +import com.cloudcraftgaming.discal.api.enums.event.EventColor; +import com.cloudcraftgaming.discal.api.enums.event.EventFrequency; +import com.cloudcraftgaming.discal.api.object.GuildSettings; +import com.cloudcraftgaming.discal.api.object.calendar.CalendarData; +import com.cloudcraftgaming.discal.api.object.event.EventData; +import com.cloudcraftgaming.discal.api.object.event.Recurrence; +import com.cloudcraftgaming.discal.api.object.web.WebGuild; +import com.cloudcraftgaming.discal.api.utils.EventUtils; +import com.cloudcraftgaming.discal.api.utils.ImageUtils; +import com.cloudcraftgaming.discal.logger.Logger; +import com.cloudcraftgaming.discal.web.handler.DiscordAccountHandler; +import com.cloudcraftgaming.discal.web.utils.ResponseUtils; +import com.google.api.client.util.DateTime; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.model.Event; +import com.google.api.services.calendar.model.EventDateTime; +import com.google.api.services.calendar.model.Events; +import org.json.JSONObject; +import spark.Request; +import spark.Response; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("Duplicates") +public class EventEndpoint { + public static String getEventsForMonth(Request request, Response response) { + JSONObject requestBody = new JSONObject(request.body()); + + Integer daysInMonth = Integer.valueOf(requestBody.getString("DaysInMonth")); + Long startEpoch = Long.valueOf(requestBody.getString("StartEpoch")); + Long endEpoch = startEpoch + (86400000L * daysInMonth); + GuildSettings settings; + + if (DiscordAccountHandler.getHandler().hasAccount(request.session().id())) { + Map m = DiscordAccountHandler.getHandler().getAccount(request.session().id()); + WebGuild g = (WebGuild) m.get("selected"); + g.setSettings(DatabaseManager.getManager().getSettings(Long.valueOf(g.getId()))); + settings = g.getSettings(); + } else { + long guildId = requestBody.getLong("guild_id"); + settings = DatabaseManager.getManager().getSettings(guildId); + } + + //okay, lets actually get the month's events. + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + Events events = service.events().list(calendarData.getCalendarAddress()) + .setTimeMin(new DateTime(startEpoch)) + .setTimeMax(new DateTime(endEpoch)) + .setOrderBy("startTime") + .setSingleEvents(true) + .setShowDeleted(false) + .execute(); + List items = events.getItems(); + + List eventsJson = new ArrayList<>(); + for (Event e: items) { + JSONObject jo = new JSONObject(); + jo.put("id", e.getId()); + jo.put("epochStart", e.getStart().getDateTime().getValue()); + jo.put("epochEnd", e.getEnd().getDateTime().getValue()); + + eventsJson.add(jo); + } + + JSONObject body = new JSONObject(); + body.put("events", eventsJson); + body.put("count", eventsJson.size() + ""); + + response.body(body.toString()); + } catch (Exception e) { + response.body("Internal server error!"); + Logger.getLogger().exception(null, "[WEB] Failed to retrieve events for a month.", e, EventEndpoint.class, true); + return response.body(); + } + return response.body(); + } + + public static String getEventsForSelectedDate(Request request, Response response) { + JSONObject requestBody = new JSONObject(request.body()); + Long startEpoch = Long.valueOf(requestBody.getString("StartEpoch")); + Long endEpoch = startEpoch + 86400000L; + GuildSettings settings; + + if (DiscordAccountHandler.getHandler().hasAccount(request.session().id())) { + Map m = DiscordAccountHandler.getHandler().getAccount(request.session().id()); + WebGuild g = (WebGuild) m.get("selected"); + g.setSettings(DatabaseManager.getManager().getSettings(Long.valueOf(g.getId()))); + settings = g.getSettings(); + } else { + long guildId = requestBody.getLong("guild_id"); + settings = DatabaseManager.getManager().getSettings(guildId); + } + + //okay, lets actually get the month's events. + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + Events events = service.events().list(calendarData.getCalendarAddress()) + .setTimeMin(new DateTime(startEpoch)) + .setTimeMax(new DateTime(endEpoch)) + .setOrderBy("startTime") + .setSingleEvents(true) + .setShowDeleted(false) + .execute(); + List items = events.getItems(); + + String tz = "Error/Unknown"; + try { + tz = service.calendars().get(calendarData.getCalendarAddress()).execute().getTimeZone(); + } catch (Exception ignore) { + } + + List eventsJson = new ArrayList<>(); + for (Event e: items) { + JSONObject jo = new JSONObject(); + jo.put("id", e.getId()); + jo.put("epochStart", e.getStart().getDateTime().getValue()); + jo.put("epochEnd", e.getEnd().getDateTime().getValue()); + jo.put("timezone", tz); + jo.put("summary", e.getSummary()); + jo.put("description", e.getDescription()); + if (e.getLocked() != null) + jo.put("location", e.getLocation()); + else + jo.put("location", "N/a"); + + jo.put("color", EventColor.fromNameOrHexOrID(e.getColorId()).name()); + jo.put("isParent", !(e.getId().contains("_"))); + + if (e.getRecurrence() != null && e.getRecurrence().size() > 0) { + jo.put("recur", true); + Recurrence r = new Recurrence().fromRRule(e.getRecurrence().get(0)); + + JSONObject rjo = new JSONObject(); + rjo.put("frequency", r.getFrequency().name()); + rjo.put("count", r.getCount()); + rjo.put("interval", r.getInterval()); + + jo.put("recurrence", rjo); + } else { + jo.put("recur", false); + + JSONObject rjo = new JSONObject(); + rjo.put("frequency", EventFrequency.DAILY.name()); + rjo.put("count", -1); + rjo.put("interval", 1); + + jo.put("recurrence", rjo); + } + + EventData ed = DatabaseManager.getManager().getEventData(settings.getGuildID(), e.getId()); + + jo.put("image", ed.getImageLink()); + + eventsJson.add(jo); + } + + JSONObject body = new JSONObject(); + body.put("events", eventsJson); + body.put("count", eventsJson.size()); + + response.body(body.toString()); + } catch (Exception e) { + response.body("Internal server error!"); + Logger.getLogger().exception(null, "[WEB] Failed to retrieve events for specific date!", e, EventEndpoint.class, true); + return response.body(); + } + return response.body(); + } + + public static String updateEvent(Request request, Response response) { + JSONObject body = new JSONObject(request.body()); + String eventId = body.getString("id"); + GuildSettings settings; + + if (DiscordAccountHandler.getHandler().hasAccount(request.session().id())) { + Map m = DiscordAccountHandler.getHandler().getAccount(request.session().id()); + WebGuild g = (WebGuild) m.get("selected"); + g.setSettings(DatabaseManager.getManager().getSettings(Long.valueOf(g.getId()))); + settings = g.getSettings(); + } else { + long guildId = body.getLong("guild_id"); + settings = DatabaseManager.getManager().getSettings(guildId); + } + + //Okay, time to update the event + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + com.google.api.services.calendar.model.Calendar cal = service.calendars().get(calendarData.getCalendarId()).execute(); + + Event event = new Event(); + event.setId(eventId); + event.setVisibility("web/public"); + event.setSummary(body.getString("summary")); + event.setDescription(body.getString("description")); + + EventDateTime start = new EventDateTime(); + start.setDateTime(new DateTime(body.getLong("epochStart"))); + event.setStart(start.setTimeZone(cal.getTimeZone())); + + EventDateTime end = new EventDateTime(); + end.setDateTime(new DateTime(body.getLong("epochEnd"))); + event.setEnd(end.setTimeZone(cal.getTimeZone())); + + if (!body.getString("color").equalsIgnoreCase("NONE")) + event.setColorId(EventColor.fromNameOrHexOrID(body.getString("color")).getId() + ""); + + if (!body.getString("location").equalsIgnoreCase("") || !body.getString("location").equalsIgnoreCase("N/a")) + event.setLocation(body.getString("location")); + + JSONObject recur = body.getJSONObject("recurrence"); + if (recur.getBoolean("recur")) { + //Handle recur + Recurrence recurrence = new Recurrence(); + recurrence.setFrequency(EventFrequency.fromValue(recur.getString("frequency"))); + recurrence.setCount(recur.getInt("count")); + recurrence.setInterval(recur.getInt("interval")); + + String[] rr = new String[]{recurrence.toRRule()}; + event.setRecurrence(Arrays.asList(rr)); + } + + EventData ed = new EventData(settings.getGuildID()); + if (!body.getString("image").equalsIgnoreCase("")) { + ed.setImageLink(body.getString("image")); + ed.setEventId(eventId); + ed.setEventEnd(event.getEnd().getDateTime().getValue()); + + if (!ImageUtils.validate(ed.getImageLink())) { + response.status(400); + JSONObject respondBody = new JSONObject(); + respondBody.put("Message", "Failed to create event!"); + respondBody.put("reason", "Invalid image link and/or GIF image not supported."); + + response.body(respondBody.toString()); + + return response.body(); + } + } + + if (ed.shouldBeSaved()) + DatabaseManager.getManager().updateEventData(ed); + + service.events().update(calendarData.getCalendarId(), eventId, event).execute(); + + response.status(200); + response.body(ResponseUtils.getJsonResponseMessage("Successfully updated event!")); + + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB] Failed to update event!", e, EventEndpoint.class, true); + e.printStackTrace(); + + JSONObject respondBody = new JSONObject(); + respondBody.put("Message", "Failed to create event!"); + respondBody.put("reason", "Google API may be at fault. Please try again."); + + response.body(respondBody.toString()); + } + + return response.body(); + } + + public static String createEvent(Request request, Response response) { + JSONObject body = new JSONObject(request.body()); + GuildSettings settings; + + if (DiscordAccountHandler.getHandler().hasAccount(request.session().id())) { + Map m = DiscordAccountHandler.getHandler().getAccount(request.session().id()); + WebGuild g = (WebGuild) m.get("selected"); + g.setSettings(DatabaseManager.getManager().getSettings(Long.valueOf(g.getId()))); + settings = g.getSettings(); + } else { + long guildId = body.getLong("guild_id"); + settings = DatabaseManager.getManager().getSettings(guildId); + } + + //Okay, time to create the event + try { + Calendar service = CalendarAuth.getCalendarService(settings); + + CalendarData calendarData = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()); + com.google.api.services.calendar.model.Calendar cal = service.calendars().get(calendarData.getCalendarId()).execute(); + + Event event = new Event(); + event.setId(KeyGenerator.generateEventId()); + event.setVisibility("web/public"); + event.setSummary(body.getString("summary")); + event.setDescription(body.getString("description")); + + EventDateTime start = new EventDateTime(); + start.setDateTime(new DateTime(body.getLong("epochStart"))); + event.setStart(start.setTimeZone(cal.getTimeZone())); + + EventDateTime end = new EventDateTime(); + end.setDateTime(new DateTime(body.getLong("epochEnd"))); + event.setEnd(end.setTimeZone(cal.getTimeZone())); + + if (!body.getString("color").equalsIgnoreCase("NONE")) + event.setColorId(EventColor.fromNameOrHexOrID(body.getString("color")).getId() + ""); + + if (!body.getString("location").equalsIgnoreCase("") || !body.getString("location").equalsIgnoreCase("N/a")) + event.setLocation(body.getString("location")); + + JSONObject recur = body.getJSONObject("recurrence"); + if (recur.getBoolean("recur")) { + //Handle recur + Recurrence recurrence = new Recurrence(); + recurrence.setFrequency(EventFrequency.fromValue(recur.getString("frequency"))); + recurrence.setCount(recur.getInt("count")); + recurrence.setInterval(recur.getInt("interval")); + + String[] rr = new String[]{recurrence.toRRule()}; + event.setRecurrence(Arrays.asList(rr)); + } + + EventData ed = new EventData(settings.getGuildID()); + ed.setEventId(event.getId()); + + if (!body.getString("image").equalsIgnoreCase("")) { + ed.setImageLink(body.getString("image")); + ed.setEventEnd(event.getEnd().getDateTime().getValue()); + + if (!ImageUtils.validate(ed.getImageLink())) { + response.status(400); + JSONObject respondBody = new JSONObject(); + respondBody.put("Message", "Failed to create event!"); + respondBody.put("reason", "Invalid image link and/or GIF image not supported."); + + response.body(respondBody.toString()); + + return response.body(); + } + } + + + if (ed.shouldBeSaved()) + DatabaseManager.getManager().updateEventData(ed); + + Event confirmed = service.events().insert(calendarData.getCalendarId(), event).execute(); + + response.status(200); + JSONObject respondBody = new JSONObject(); + respondBody.put("Message", "Successfully create event!"); + respondBody.put("id", confirmed.getId()); + + response.body(respondBody.toString()); + + } catch (Exception e) { + Logger.getLogger().exception(null, "[WEB] Failed to create event!", e, EventEndpoint.class, true); + e.printStackTrace(); + + JSONObject respondBody = new JSONObject(); + respondBody.put("Message", "Failed to create event!"); + respondBody.put("reason", "Google API may be at fault. Please try again."); + + response.body(respondBody.toString()); + } + + return response.body(); + } + + public static String deleteEvent(Request request, Response response) { + JSONObject requestBody = new JSONObject(request.body()); + String eventId = requestBody.getString("id"); + GuildSettings settings; + + //Check if logged in, else get guild ID from body. + if (DiscordAccountHandler.getHandler().hasAccount(request.session().id())) { + Map m = DiscordAccountHandler.getHandler().getAccount(request.session().id()); + WebGuild g = (WebGuild) m.get("selected"); + g.setSettings(DatabaseManager.getManager().getSettings(Long.valueOf(g.getId()))); + settings = g.getSettings(); + } else { + long guildId = requestBody.getLong("guild_id"); + settings = DatabaseManager.getManager().getSettings(guildId); + } + + //okay, time to properly delete the event + if (EventUtils.deleteEvent(settings, eventId)) { + //Deleted! + response.body(ResponseUtils.getJsonResponseMessage("Successfully deleted event!")); + } else { + //Oh nos! we failed >.< + response.status(500); + response.body(ResponseUtils.getJsonResponseMessage("Failed to delete event!")); + } + + return response.body(); + } +} \ No newline at end of file diff --git a/Website/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/GuildEndpoint.java b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/GuildEndpoint.java similarity index 100% rename from Website/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/GuildEndpoint.java rename to src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/GuildEndpoint.java diff --git a/Website/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/RsvpEndpoint.java b/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/RsvpEndpoint.java similarity index 100% rename from Website/src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/RsvpEndpoint.java rename to src/main/java/com/cloudcraftgaming/discal/web/endpoints/v1/RsvpEndpoint.java diff --git a/Website/src/main/java/com/cloudcraftgaming/discal/web/handler/DashboardHandler.java b/src/main/java/com/cloudcraftgaming/discal/web/handler/DashboardHandler.java similarity index 100% rename from Website/src/main/java/com/cloudcraftgaming/discal/web/handler/DashboardHandler.java rename to src/main/java/com/cloudcraftgaming/discal/web/handler/DashboardHandler.java diff --git a/src/main/java/com/cloudcraftgaming/discal/web/handler/DiscordAccountHandler.java b/src/main/java/com/cloudcraftgaming/discal/web/handler/DiscordAccountHandler.java new file mode 100644 index 00000000..c4c6c03c --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/handler/DiscordAccountHandler.java @@ -0,0 +1,171 @@ +package com.cloudcraftgaming.discal.web.handler; + +import com.cloudcraftgaming.discal.api.DisCalAPI; +import com.cloudcraftgaming.discal.api.object.BotSettings; +import com.cloudcraftgaming.discal.api.object.web.WebGuild; +import com.cloudcraftgaming.discal.api.utils.GuildUtils; +import sx.blah.discord.handle.obj.IGuild; + +import java.time.LocalDate; +import java.util.*; + +/** + * Created by Nova Fox on 12/19/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +@SuppressWarnings("unchecked") +public class DiscordAccountHandler { + private static DiscordAccountHandler instance; + private static Timer timer; + + private HashMap discordAccounts = new HashMap<>(); + + //Instance handling + private DiscordAccountHandler() { + } //Prevent initialization + + public static DiscordAccountHandler getHandler() { + if (instance == null) + instance = new DiscordAccountHandler(); + + return instance; + } + + public void init() { + if (BotSettings.RUN_API.get().equalsIgnoreCase("true")) { + timer = new Timer(true); + timer.schedule(new TimerTask() { + @Override + public void run() { + removeTimedOutAccounts(); + } + }, 60 * 30 * 1000); + } + } + + public void shutdown() { + if (timer != null) + timer.cancel(); + } + + //Boolean/checkers + public boolean hasAccount(String sessionId) { + return discordAccounts.containsKey(sessionId); + } + + //Getters + public Map getAccount(String sessionId) { + if (discordAccounts.containsKey(sessionId)) { + Map m = discordAccounts.get(sessionId); + m.remove("lastUse"); + m.put("lastUse", System.currentTimeMillis()); + return m; + } else { + //Not logged in... + Map m = new HashMap(); + m.put("loggedIn", false); + m.put("client", BotSettings.ID.get()); + m.put("year", LocalDate.now().getYear()); + m.put("redirUri", BotSettings.REDIR_URI.get()); + return m; + } + } + + public Map getAccountForGuildEmbed(String sessionId, String guildId) { + if (discordAccounts.containsKey(sessionId)) { + Map m = discordAccounts.get(sessionId); + m.remove("lastUse"); + m.put("lastUse", System.currentTimeMillis()); + + //Add guild for guild embed + m.remove("embed"); + IGuild g = DisCalAPI.getAPI().getClient().getGuildByID(Long.valueOf(guildId)); + WebGuild wg = new WebGuild().fromGuild(g); + + m.put("embed", wg); + + return m; + } else { + //Not logged in... + Map m = new HashMap(); + m.put("loggedIn", false); + m.put("client", BotSettings.ID.get()); + m.put("year", LocalDate.now().getYear()); + + //Add guild for guild embed + IGuild g = DisCalAPI.getAPI().getClient().getGuildByID(Long.valueOf(guildId)); + WebGuild wg = new WebGuild().fromGuild(g); + + m.put("embed", wg); + return m; + } + } + + public Map findAccount(String userId) { + for (Map m: discordAccounts.values()) { + if (m.containsKey("id")) { + if (m.get("id").equals(userId)) { + m.remove("lastUse"); + m.put("lastUse", System.currentTimeMillis()); + return m; + } + } + } + return null; + } + + public int accountCount() { + return discordAccounts.size(); + } + + //Functions + public void addAccount(Map m, String sessionId) { + discordAccounts.remove(sessionId); + m.remove("lastUse"); + m.put("lastUse", System.currentTimeMillis()); + discordAccounts.put(sessionId, m); + } + + public void appendAccount(Map m, String sessionId) { + if (discordAccounts.containsKey(sessionId)) { + Map exist = discordAccounts.get(sessionId); + exist.remove("lastUse"); + exist.put("lastUse", System.currentTimeMillis()); + exist.putAll(m); + } else { + discordAccounts.put(sessionId, m); + } + } + + public void updateAccount(String userId) { + Map m = findAccount(userId); + if (m != null) { + m.remove("guilds"); + m.put("guilds", GuildUtils.getGuilds(userId)); + m.remove("lastUse"); + m.put("lastUse", System.currentTimeMillis()); + } + } + + public void removeAccount(String sessionId) { + if (hasAccount(sessionId)) { + discordAccounts.remove(sessionId); + } + } + + private void removeTimedOutAccounts() { + long limit = Long.valueOf(BotSettings.TIME_OUT.get()); + final List toRemove = new ArrayList<>(); + for (String id: discordAccounts.keySet()) { + Map m = discordAccounts.get(id); + long lastUse = (long) m.get("lastUse"); + if (System.currentTimeMillis() - lastUse > limit) + toRemove.remove(id); //Timed out, remove account info and require sign in. + } + + for (String id: toRemove) { + discordAccounts.remove(id); + } + } +} \ No newline at end of file diff --git a/Website/src/main/java/com/cloudcraftgaming/discal/web/network/discord/DiscordLoginHandler.java b/src/main/java/com/cloudcraftgaming/discal/web/network/discord/DiscordLoginHandler.java similarity index 100% rename from Website/src/main/java/com/cloudcraftgaming/discal/web/network/discord/DiscordLoginHandler.java rename to src/main/java/com/cloudcraftgaming/discal/web/network/discord/DiscordLoginHandler.java diff --git a/src/main/java/com/cloudcraftgaming/discal/web/utils/ResponseUtils.java b/src/main/java/com/cloudcraftgaming/discal/web/utils/ResponseUtils.java new file mode 100644 index 00000000..2693a547 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/utils/ResponseUtils.java @@ -0,0 +1,12 @@ +package com.cloudcraftgaming.discal.web.utils; + +/** + * Created by Nova Fox on 11/10/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class ResponseUtils { + public static String getJsonResponseMessage(String msg) { + return "{\"Message\": \"" + msg + "\"}"; + } +} \ No newline at end of file diff --git a/Website/src/main/java/com/cloudcraftgaming/discal/web/utils/SparkUtils.java b/src/main/java/com/cloudcraftgaming/discal/web/utils/SparkUtils.java similarity index 100% rename from Website/src/main/java/com/cloudcraftgaming/discal/web/utils/SparkUtils.java rename to src/main/java/com/cloudcraftgaming/discal/web/utils/SparkUtils.java diff --git a/src/main/java/com/cloudcraftgaming/discal/web/utils/ThymeleafTemplateEngine.java b/src/main/java/com/cloudcraftgaming/discal/web/utils/ThymeleafTemplateEngine.java new file mode 100644 index 00000000..8ee07d25 --- /dev/null +++ b/src/main/java/com/cloudcraftgaming/discal/web/utils/ThymeleafTemplateEngine.java @@ -0,0 +1,102 @@ +package com.cloudcraftgaming.discal.web.utils; + +import org.thymeleaf.context.Context; +import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; +import org.thymeleaf.templateresolver.ITemplateResolver; +import spark.ModelAndView; +import spark.TemplateEngine; + +import java.util.Locale; +import java.util.Map; + +/** + * Created by Nova Fox on 12/19/17. + * Website: www.cloudcraftgaming.com + * For Project: DisCal-Discord-Bot + */ +public class ThymeleafTemplateEngine extends TemplateEngine { + + private static final String DEFAULT_PREFIX = "web/public/"; + private static final String DEFAULT_SUFFIX = ".html"; + private static final long DEFAULT_CACHE_TTL_MS = 3600000L; + + private org.thymeleaf.TemplateEngine templateEngine; + + /** + * Constructs a default thymeleaf template engine. + * Defaults prefix (template directory in resource path) to templates/ and suffix to .html + */ + public ThymeleafTemplateEngine() { + this(DEFAULT_PREFIX, DEFAULT_SUFFIX); + } + + /** + * Constructs a thymeleaf template engine with specified prefix and suffix + * + * @param prefix the prefix (template directory in resource path) + * @param suffix the suffix (e.g. .html) + */ + public ThymeleafTemplateEngine(String prefix, String suffix) { + ITemplateResolver defaultTemplateResolver = createDefaultTemplateResolver(prefix, suffix); + initialize(defaultTemplateResolver); + } + + /** + * Constructs a thymeleaf template engine with a proprietary initialize + * + * @param templateResolver the template resolver. + */ + public ThymeleafTemplateEngine(ITemplateResolver templateResolver) { + initialize(templateResolver); + } + + private static ITemplateResolver createDefaultTemplateResolver(String prefix, String suffix) { + final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); + templateResolver.setTemplateMode(TemplateMode.HTML); + + templateResolver.setPrefix(prefix != null ? prefix : DEFAULT_PREFIX); + + templateResolver.setSuffix(suffix != null ? suffix : DEFAULT_SUFFIX); + + templateResolver.setCacheTTLMs(DEFAULT_CACHE_TTL_MS); + return templateResolver; + } + + /** + * Initializes and sets the template resolver + */ + private void initialize(ITemplateResolver templateResolver) { + templateEngine = new org.thymeleaf.TemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + templateEngine.addDialect(new Java8TimeDialect()); + } + + @Override + @SuppressWarnings("unchecked") + public String render(ModelAndView modelAndView) { + return render(modelAndView, Locale.getDefault()); + } + + /** + * Process the specified template (usually the template name). + * Output will be written into a String that will be returned from calling this method, + * once template processing has finished. + * + * @param modelAndView model and view + * @param locale A Locale object represents a specific geographical, political, or cultural region + * @return processed template + */ + public String render(ModelAndView modelAndView, Locale locale) { + Object model = modelAndView.getModel(); + + if (model instanceof Map) { + Context context = new Context(locale); + context.setVariables((Map) model); + return templateEngine.process(modelAndView.getViewName(), context); + } else { + throw new IllegalArgumentException("modelAndView.getModel() must return a java.util.Map"); + } + } +} \ No newline at end of file diff --git a/Bot/src/main/resources/languages/ENGLISH.json b/src/main/resources/languages/ENGLISH.json similarity index 100% rename from Bot/src/main/resources/languages/ENGLISH.json rename to src/main/resources/languages/ENGLISH.json diff --git a/Bot/src/main/resources/languages/TEMPLATE.json b/src/main/resources/languages/TEMPLATE.json similarity index 100% rename from Bot/src/main/resources/languages/TEMPLATE.json rename to src/main/resources/languages/TEMPLATE.json diff --git a/Website/src/main/resources/web/public/assets/files/Lazy-DisCal/Windows/Lazy_Discal_GUI-latest.exe b/src/main/resources/web/public/assets/files/Lazy-DisCal/Windows/Lazy_Discal_GUI-latest.exe similarity index 100% rename from Website/src/main/resources/web/public/assets/files/Lazy-DisCal/Windows/Lazy_Discal_GUI-latest.exe rename to src/main/resources/web/public/assets/files/Lazy-DisCal/Windows/Lazy_Discal_GUI-latest.exe diff --git a/Website/src/main/resources/web/public/assets/images/event/event-color-chart.jpg b/src/main/resources/web/public/assets/images/event/event-color-chart.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/event/event-color-chart.jpg rename to src/main/resources/web/public/assets/images/event/event-color-chart.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Announcement-Example.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Announcement-Example.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Announcement-Example.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Announcement-Example.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Creation.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Creation.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Creation.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Creation.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Example.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Example.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Example.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Calendar-Example.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Developer-API.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Developer-API.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Developer-API.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Developer-API.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Event-Creation.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Event-Creation.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Event-Creation.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Event-Creation.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Invite-Perms.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Invite-Perms.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Invite-Perms.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Invite-Perms.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/DisCal-Role-Perms.jpg b/src/main/resources/web/public/assets/images/examples/DisCal-Role-Perms.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/DisCal-Role-Perms.jpg rename to src/main/resources/web/public/assets/images/examples/DisCal-Role-Perms.jpg diff --git a/Website/src/main/resources/web/public/assets/images/examples/announcement_demo.gif b/src/main/resources/web/public/assets/images/examples/announcement_demo.gif similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/announcement_demo.gif rename to src/main/resources/web/public/assets/images/examples/announcement_demo.gif diff --git a/Website/src/main/resources/web/public/assets/images/examples/calendar_demo.gif b/src/main/resources/web/public/assets/images/examples/calendar_demo.gif similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/calendar_demo.gif rename to src/main/resources/web/public/assets/images/examples/calendar_demo.gif diff --git a/Website/src/main/resources/web/public/assets/images/examples/event_demo.gif b/src/main/resources/web/public/assets/images/examples/event_demo.gif similarity index 100% rename from Website/src/main/resources/web/public/assets/images/examples/event_demo.gif rename to src/main/resources/web/public/assets/images/examples/event_demo.gif diff --git a/Website/src/main/resources/web/public/assets/images/lazy-discal/lazy-discal-program.jpg b/src/main/resources/web/public/assets/images/lazy-discal/lazy-discal-program.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/lazy-discal/lazy-discal-program.jpg rename to src/main/resources/web/public/assets/images/lazy-discal/lazy-discal-program.jpg diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg x128.png b/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg x128.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg x128.png rename to src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg x128.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg.png b/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg.png rename to src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo Dark +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo+Type Dark +bg.png b/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo+Type Dark +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo+Type Dark +bg.png rename to src/main/resources/web/public/assets/images/logos/Dark/Opaque/Logo+Type Dark +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Dark +bg.png b/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Dark +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Dark +bg.png rename to src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Dark +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Square Dark +bg.png b/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Square Dark +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Square Dark +bg.png rename to src/main/resources/web/public/assets/images/logos/Dark/Opaque/Type Square Dark +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo Dark.png b/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo Dark.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo Dark.png rename to src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo Dark.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo+Type Dark.png b/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo+Type Dark.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo+Type Dark.png rename to src/main/resources/web/public/assets/images/logos/Dark/Transparent/Logo+Type Dark.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Type Dark.png b/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Type Dark.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/Type Dark.png rename to src/main/resources/web/public/assets/images/logos/Dark/Transparent/Type Dark.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/type Square Dark.png b/src/main/resources/web/public/assets/images/logos/Dark/Transparent/type Square Dark.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Dark/Transparent/type Square Dark.png rename to src/main/resources/web/public/assets/images/logos/Dark/Transparent/type Square Dark.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo Light +bg.png b/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo Light +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo Light +bg.png rename to src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo Light +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo+Type Light +bg.png b/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo+Type Light +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo+Type Light +bg.png rename to src/main/resources/web/public/assets/images/logos/Light/Opaque/Logo+Type Light +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Light +bg.png b/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Light +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Light +bg.png rename to src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Light +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Square Light +bg.png b/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Square Light +bg.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Square Light +bg.png rename to src/main/resources/web/public/assets/images/logos/Light/Opaque/Type Square Light +bg.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo Light.png b/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo Light.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo Light.png rename to src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo Light.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo+Type Light.png b/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo+Type Light.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo+Type Light.png rename to src/main/resources/web/public/assets/images/logos/Light/Transparent/Logo+Type Light.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Light.png b/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Light.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Light.png rename to src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Light.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Square Light.png b/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Square Light.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Square Light.png rename to src/main/resources/web/public/assets/images/logos/Light/Transparent/Type Square Light.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/discord-logo-white.png b/src/main/resources/web/public/assets/images/logos/discord-logo-white.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/discord-logo-white.png rename to src/main/resources/web/public/assets/images/logos/discord-logo-white.png diff --git a/Website/src/main/resources/web/public/assets/images/logos/embed-icon.png b/src/main/resources/web/public/assets/images/logos/embed-icon.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/logos/embed-icon.png rename to src/main/resources/web/public/assets/images/logos/embed-icon.png diff --git a/Website/src/main/resources/web/public/assets/images/other/discal-github.jpg b/src/main/resources/web/public/assets/images/other/discal-github.jpg similarity index 100% rename from Website/src/main/resources/web/public/assets/images/other/discal-github.jpg rename to src/main/resources/web/public/assets/images/other/discal-github.jpg diff --git a/Website/src/main/resources/web/public/assets/images/other/discal-trello.png b/src/main/resources/web/public/assets/images/other/discal-trello.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/other/discal-trello.png rename to src/main/resources/web/public/assets/images/other/discal-trello.png diff --git a/Website/src/main/resources/web/public/assets/images/other/novafox-patreon-page.png b/src/main/resources/web/public/assets/images/other/novafox-patreon-page.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/other/novafox-patreon-page.png rename to src/main/resources/web/public/assets/images/other/novafox-patreon-page.png diff --git a/Website/src/main/resources/web/public/assets/images/other/support-server.png b/src/main/resources/web/public/assets/images/other/support-server.png similarity index 100% rename from Website/src/main/resources/web/public/assets/images/other/support-server.png rename to src/main/resources/web/public/assets/images/other/support-server.png diff --git a/Website/src/main/resources/web/public/pages/about.html b/src/main/resources/web/public/pages/about.html similarity index 100% rename from Website/src/main/resources/web/public/pages/about.html rename to src/main/resources/web/public/pages/about.html diff --git a/Website/src/main/resources/web/public/pages/commands.html b/src/main/resources/web/public/pages/commands.html similarity index 100% rename from Website/src/main/resources/web/public/pages/commands.html rename to src/main/resources/web/public/pages/commands.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/components/announcements.html b/src/main/resources/web/public/pages/dashboard/components/announcements.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/components/announcements.html rename to src/main/resources/web/public/pages/dashboard/components/announcements.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/components/calendar.html b/src/main/resources/web/public/pages/dashboard/components/calendar.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/components/calendar.html rename to src/main/resources/web/public/pages/dashboard/components/calendar.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/components/events.html b/src/main/resources/web/public/pages/dashboard/components/events.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/components/events.html rename to src/main/resources/web/public/pages/dashboard/components/events.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/components/rsvp.html b/src/main/resources/web/public/pages/dashboard/components/rsvp.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/components/rsvp.html rename to src/main/resources/web/public/pages/dashboard/components/rsvp.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/dashboard.html b/src/main/resources/web/public/pages/dashboard/dashboard.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/dashboard.html rename to src/main/resources/web/public/pages/dashboard/dashboard.html diff --git a/Website/src/main/resources/web/public/pages/dashboard/guild.html b/src/main/resources/web/public/pages/dashboard/guild.html similarity index 100% rename from Website/src/main/resources/web/public/pages/dashboard/guild.html rename to src/main/resources/web/public/pages/dashboard/guild.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/errors.html b/src/main/resources/web/public/pages/docs/api/errors.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/errors.html rename to src/main/resources/web/public/pages/docs/api/errors.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/overview.html b/src/main/resources/web/public/pages/docs/api/overview.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/overview.html rename to src/main/resources/web/public/pages/docs/api/overview.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/v1/announcement.html b/src/main/resources/web/public/pages/docs/api/v1/announcement.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/v1/announcement.html rename to src/main/resources/web/public/pages/docs/api/v1/announcement.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/v1/calendar.html b/src/main/resources/web/public/pages/docs/api/v1/calendar.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/v1/calendar.html rename to src/main/resources/web/public/pages/docs/api/v1/calendar.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/v1/events.html b/src/main/resources/web/public/pages/docs/api/v1/events.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/v1/events.html rename to src/main/resources/web/public/pages/docs/api/v1/events.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/v1/guild.html b/src/main/resources/web/public/pages/docs/api/v1/guild.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/v1/guild.html rename to src/main/resources/web/public/pages/docs/api/v1/guild.html diff --git a/Website/src/main/resources/web/public/pages/docs/api/v1/rsvp.html b/src/main/resources/web/public/pages/docs/api/v1/rsvp.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/api/v1/rsvp.html rename to src/main/resources/web/public/pages/docs/api/v1/rsvp.html diff --git a/Website/src/main/resources/web/public/pages/docs/events/event-colors.html b/src/main/resources/web/public/pages/docs/events/event-colors.html similarity index 100% rename from Website/src/main/resources/web/public/pages/docs/events/event-colors.html rename to src/main/resources/web/public/pages/docs/events/event-colors.html diff --git a/Website/src/main/resources/web/public/pages/embed/calendar.html b/src/main/resources/web/public/pages/embed/calendar.html similarity index 100% rename from Website/src/main/resources/web/public/pages/embed/calendar.html rename to src/main/resources/web/public/pages/embed/calendar.html diff --git a/Website/src/main/resources/web/public/pages/index.html b/src/main/resources/web/public/pages/index.html similarity index 100% rename from Website/src/main/resources/web/public/pages/index.html rename to src/main/resources/web/public/pages/index.html diff --git a/Website/src/main/resources/web/public/pages/lazy-discal.html b/src/main/resources/web/public/pages/lazy-discal.html similarity index 100% rename from Website/src/main/resources/web/public/pages/lazy-discal.html rename to src/main/resources/web/public/pages/lazy-discal.html diff --git a/Website/src/main/resources/web/public/pages/policy/privacy.html b/src/main/resources/web/public/pages/policy/privacy.html similarity index 100% rename from Website/src/main/resources/web/public/pages/policy/privacy.html rename to src/main/resources/web/public/pages/policy/privacy.html diff --git a/Website/src/main/resources/web/public/pages/setup.html b/src/main/resources/web/public/pages/setup.html similarity index 100% rename from Website/src/main/resources/web/public/pages/setup.html rename to src/main/resources/web/public/pages/setup.html diff --git a/Website/src/main/resources/web/public/scripts/dashboard/announcement.js b/src/main/resources/web/public/scripts/dashboard/announcement.js similarity index 100% rename from Website/src/main/resources/web/public/scripts/dashboard/announcement.js rename to src/main/resources/web/public/scripts/dashboard/announcement.js diff --git a/Website/src/main/resources/web/public/scripts/dashboard/calendar.js b/src/main/resources/web/public/scripts/dashboard/calendar.js similarity index 100% rename from Website/src/main/resources/web/public/scripts/dashboard/calendar.js rename to src/main/resources/web/public/scripts/dashboard/calendar.js diff --git a/Website/src/main/resources/web/public/scripts/embed/calendar.js b/src/main/resources/web/public/scripts/embed/calendar.js similarity index 100% rename from Website/src/main/resources/web/public/scripts/embed/calendar.js rename to src/main/resources/web/public/scripts/embed/calendar.js diff --git a/Website/src/main/resources/web/public/scripts/snackbar.js b/src/main/resources/web/public/scripts/snackbar.js similarity index 100% rename from Website/src/main/resources/web/public/scripts/snackbar.js rename to src/main/resources/web/public/scripts/snackbar.js diff --git a/Website/src/main/resources/web/public/styles/bootstrap/modal-only.css b/src/main/resources/web/public/styles/bootstrap/modal-only.css similarity index 100% rename from Website/src/main/resources/web/public/styles/bootstrap/modal-only.css rename to src/main/resources/web/public/styles/bootstrap/modal-only.css diff --git a/Website/src/main/resources/web/public/styles/calendar.css b/src/main/resources/web/public/styles/calendar.css similarity index 100% rename from Website/src/main/resources/web/public/styles/calendar.css rename to src/main/resources/web/public/styles/calendar.css diff --git a/Website/src/main/resources/web/public/styles/docs.css b/src/main/resources/web/public/styles/docs.css similarity index 100% rename from Website/src/main/resources/web/public/styles/docs.css rename to src/main/resources/web/public/styles/docs.css diff --git a/Website/src/main/resources/web/public/styles/fix.css b/src/main/resources/web/public/styles/fix.css similarity index 100% rename from Website/src/main/resources/web/public/styles/fix.css rename to src/main/resources/web/public/styles/fix.css diff --git a/Website/src/main/resources/web/public/styles/global.css b/src/main/resources/web/public/styles/global.css similarity index 100% rename from Website/src/main/resources/web/public/styles/global.css rename to src/main/resources/web/public/styles/global.css