Restructure modules. Hopefully this works

This commit is contained in:
NovaFox161
2018-05-25 12:26:29 -05:00
parent 2b2668c0d3
commit 9892bbfc30
176 changed files with 583 additions and 195 deletions

89
API/API.iml Normal file
View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.github.discord4j:Discord4J:2.10.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.8.v20171121" level="project" />
<orderEntry type="library" name="Maven: net.jodah:typetools:0.5.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-afterburner:2.9.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: net.java.dev.jna:jna:4.5.0" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:mp3spi:1.9.5.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jlayer:1.0.1.4" level="project" />
<orderEntry type="library" name="Maven: junit:junit:3.8.2" level="project" />
<orderEntry type="library" name="Maven: org.jcraft:jorbis:0.0.17" level="project" />
<orderEntry type="library" name="Maven: org.jflac:jflac-codec:1.5.2" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-share:0.3.7.4" level="project" />
<orderEntry type="library" name="Maven: org.tritonus:tritonus-dsp:0.3.6" level="project" />
<orderEntry type="library" name="Maven: com.vdurmont:emoji-java:4.0.0" level="project" />
<orderEntry type="library" name="Maven: com.koloboke:koloboke-impl-common-jdk8:1.0.0" level="project" />
<orderEntry type="library" name="Maven: com.koloboke:koloboke-api-jdk8:1.0.0" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.7" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.7" level="project" />
<orderEntry type="library" name="Maven: com.github.DiscordBotList:Java-Wrapper:v1.0" level="project" />
<orderEntry type="library" name="Maven: com.squareup.retrofit2:converter-gson:2.3.0" level="project" />
<orderEntry type="library" name="Maven: com.squareup.retrofit2:retrofit:2.3.0" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.8.0" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okio:okio:1.13.0" level="project" />
<orderEntry type="library" name="Maven: com.google.api-client:google-api-client:1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.oauth-client:google-oauth-client:1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.http-client:google-http-client:1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
<orderEntry type="library" name="Maven: com.google.http-client:google-http-client-jackson2:1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava-jdk5:17.0" level="project" />
<orderEntry type="library" name="Maven: com.google.apis:google-api-services-calendar:v3-rev225-1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.oauth-client:google-oauth-client-jetty:1.22.0" level="project" />
<orderEntry type="library" name="Maven: com.google.oauth-client:google-oauth-client-java6:1.22.0" level="project" />
<orderEntry type="library" name="Maven: org.mortbay.jetty:jetty:6.1.26" level="project" />
<orderEntry type="library" name="Maven: org.mortbay.jetty:jetty-util:6.1.26" level="project" />
<orderEntry type="library" name="Maven: org.mortbay.jetty:servlet-api:2.5-20081211" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.11" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
<orderEntry type="library" name="Maven: com.mashape.unirest:unirest-java:1.4.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.3.6" level="project" />
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.1.3" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.6" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpasyncclient:4.0.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore-nio:4.3.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpmime:4.3.6" level="project" />
<orderEntry type="library" name="Maven: org.json:json:20140107" level="project" />
<orderEntry type="library" name="Maven: joda-time:joda-time:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.6.v20170531" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.21" level="project" />
<orderEntry type="library" name="Maven: org.thymeleaf:thymeleaf:3.0.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ognl:ognl:3.1.12" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />
<orderEntry type="library" name="Maven: org.attoparser:attoparser:2.0.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.unbescape:unbescape:1.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-java8time:3.0.1.RELEASE" level="project" />
</component>
</module>

17
API/pom.xml Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cloudcraftgaming</groupId>
<artifactId>DisCal</artifactId>
<version>2.0.0</version>
</parent>
<groupId>com.cloudcraftgaming.DisCal</groupId>
<artifactId>API</artifactId>
</project>

View File

@@ -0,0 +1,27 @@
package com.cloudcraftgaming.discal.api;
import sx.blah.discord.api.IDiscordClient;
public class DisCalAPI {
private static DisCalAPI instance;
private static IDiscordClient client;
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;
}
}

View File

@@ -0,0 +1,128 @@
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.
* <p>
* If modifying these scopes, delete your previously saved credentials
* at ~/.credentials/calendar-java-quickstart
*/
private static final List<String> 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;
}
/**
* Build and return an authorized Calendar client service.
*
* @return an authorized Calendar client service
* @throws IOException In the event authorization fails.
*/
public static com.google.api.services.calendar.Calendar
getCalendarService() throws IOException {
Credential credential = authorize();
return new com.google.api.services.calendar.Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
}
public static com.google.api.services.calendar.Calendar getCalendarService(GuildSettings g) throws Exception {
Credential credential = authorize(g);
return new com.google.api.services.calendar.Calendar.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential).setApplicationName(APPLICATION_NAME).build();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,103 @@
package com.cloudcraftgaming.discal.api.database;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public abstract class Database {
protected Connection connection;
/**
* Creates a new Database
*/
protected Database() {
this.connection = null;
}
/**
* Opens a connection with the database
*
* @return Opened connection
* @throws SQLException if the connection can not be opened
* @throws ClassNotFoundException if the driver cannot be found
*/
public abstract Connection openConnection() throws SQLException, ClassNotFoundException;
/**
* Checks if a connection is open with the database
*
* @return true if the connection is open
* @throws SQLException if the connection cannot be checked
*/
public boolean checkConnection() throws SQLException {
return connection != null && !connection.isClosed();
}
/**
* Gets the connection with the database
*
* @return Connection with the database, null if none
*/
public Connection getConnection() {
return connection;
}
/**
* Closes the connection with the database
*
* @return true if successful
* @throws SQLException if the connection cannot be closed
*/
public boolean closeConnection() throws SQLException {
if (connection == null) {
return false;
}
connection.close();
return true;
}
/**
* Executes a SQL Query<br>
* <p>
* If the connection is closed, it will be opened
*
* @param query Query to be run
* @return the results of the query
* @throws SQLException If the query cannot be executed
* @throws ClassNotFoundException If the driver cannot be found; see {@link #openConnection()}
*/
public ResultSet querySQL(String query) throws SQLException, ClassNotFoundException {
if (!checkConnection()) {
openConnection();
}
Statement statement = connection.createStatement();
return statement.executeQuery(query);
}
/**
* Executes an Update SQL Query<br>
* See {@link java.sql.Statement#executeUpdate(String)}<br>
* If the connection is closed, it will be opened
*
* @param query Query to be run
* @return Result Code, see {@link java.sql.Statement#executeUpdate(String)}
* @throws SQLException If the query cannot be executed
* @throws ClassNotFoundException If the driver cannot be found; see {@link #openConnection()}
*/
public int updateSQL(String query) throws SQLException, ClassNotFoundException {
if (!checkConnection()) {
openConnection();
}
Statement statement = connection.createStatement();
return statement.executeUpdate(query);
}
}

View File

@@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
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;
}
}

View File

@@ -0,0 +1,53 @@
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;
}
}

View File

@@ -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
}

File diff suppressed because one or more lines are too long

View File

@@ -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 <code>true</code> if value, otherwise <code>false</code>.
*/
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;
}
}
}

View File

@@ -0,0 +1,108 @@
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 Integer getId() {
return id;
}
public String getHex() {
return hex;
}
public Integer getR() {
return r;
}
public Integer getG() {
return g;
}
public Integer 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 {
Integer i = Integer.valueOf(nameOrHexOrId);
if (c.getId().equals(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().equals(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 {
Integer i = Integer.valueOf(nameOrHexOrID);
if (c.getId().equals(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().equals(id)) {
return c;
}
}
return NONE;
}
}

View File

@@ -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 <code>true</code> if valid, else <code>false</code>.
*/
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;
}
}
}

View File

@@ -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<String, Map<String, String>> readAllLangFiles() {
Map<String, Map<String, String>> 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<Map<String, String>>() {
}.getType();
Map<String, String> 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;
}
}

View File

@@ -0,0 +1,243 @@
package com.cloudcraftgaming.discal.api.message;
import com.cloudcraftgaming.discal.api.DisCalAPI;
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.IChannel;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.handle.obj.IPrivateChannel;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.util.DiscordException;
import sx.blah.discord.util.MessageBuilder;
import sx.blah.discord.util.MissingPermissionsException;
import sx.blah.discord.util.RequestBuffer;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
public class Message {
/**
* Sends a message via Discord as DisCal.
*
* @param message The message to send, with formatting.
* @param event The Event received (to send to the same channel and guild).
*/
public static IMessage sendMessage(String message, MessageReceivedEvent event) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).appendContent(message).withChannel(event.getMessage().getChannel()).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
/**
* Sends a message via Discord as DisCal.
*
* @param message The message to send, with formatting.
* @param channel The channel to send the message to.
*/
public static IMessage sendMessage(String message, IChannel channel) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).appendContent(message).withChannel(channel).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
/**
* Sends a message via Discord as DisCal.
*
* @param embed The EmbedObject to append to the message.
* @param event The event received (to send to the same channel and guild).
*/
public static IMessage sendMessage(EmbedObject embed, MessageReceivedEvent event) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).withEmbed(embed).withChannel(event.getMessage().getChannel()).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
/**
* Sends a message via Discord as DisCal.
*
* @param embed The EmbedObject to append to the message.
* @param channel The channel to send the message to.
*/
public static IMessage sendMessage(EmbedObject embed, IChannel channel) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).withEmbed(embed).withChannel(channel).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
/**
* Sends a message via Discord as DisCal.
*
* @param embed The EmbedObject to append to the message.
* @param message The message to send, with formatting.
* @param event The event received (to send to the same channel and guild).
*/
public static IMessage sendMessage(EmbedObject embed, String message, MessageReceivedEvent event) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).appendContent(message).withEmbed(embed).withChannel(event.getMessage().getChannel()).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
/**
* Sends a message via Discord as DisCal.
*
* @param embed The EmbedObject to append to the message.
* @param message The message to send, with formatting.
* @param channel The channel to send the message to.
*/
public static IMessage sendMessage(EmbedObject embed, String message, IChannel channel) {
return RequestBuffer.request(() -> {
try {
return new MessageBuilder(DisCalAPI.getAPI().getClient()).appendContent(message).withEmbed(embed).withChannel(channel).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
public static void sendMessageAsync(EmbedObject embedObject, String message, IChannel channel) {
RequestBuffer.request(() -> {
try {
new MessageBuilder(DisCalAPI.getAPI().getClient()).appendContent(message).withEmbed(embedObject).withChannel(channel).build();
} catch (DiscordException | MissingPermissionsException e) {
//No reason to print exception.
}
});
}
public static IMessage sendDirectMessage(String message, IUser user) {
return RequestBuffer.request(() -> {
try {
IPrivateChannel pc = user.getOrCreatePMChannel();
return new MessageBuilder(DisCalAPI.getAPI().getClient()).withChannel(pc).appendContent(message).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
public static IMessage sendDirectMessage(EmbedObject embed, IUser user) {
return RequestBuffer.request(() -> {
try {
IPrivateChannel pc = user.getOrCreatePMChannel();
return new MessageBuilder(DisCalAPI.getAPI().getClient()).withChannel(pc).withEmbed(embed).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
public static IMessage sendDirectMessage(String message, EmbedObject embed, IUser user) {
return RequestBuffer.request(() -> {
try {
IPrivateChannel pc = user.getOrCreatePMChannel();
return new MessageBuilder(DisCalAPI.getAPI().getClient()).withChannel(pc).appendContent(message).withEmbed(embed).build();
} catch (DiscordException | MissingPermissionsException e) {
//Failed to send message.
return null;
}
}).get();
}
public static boolean deleteMessage(MessageReceivedEvent event) {
try {
return RequestBuffer.request(() -> {
try {
if (!event.getMessage().isDeleted()) {
event.getMessage().delete();
}
return true;
} catch (DiscordException | MissingPermissionsException e) {
//Failed to delete
return false;
}
}).get();
} catch (NullPointerException e) {
return false;
}
}
public static boolean deleteMessage(IMessage message) {
try {
return RequestBuffer.request(() -> {
try {
if (!message.isDeleted()) {
message.delete();
}
return true;
} catch (DiscordException | MissingPermissionsException e) {
//Failed to delete.
return false;
}
}).get();
} catch (NullPointerException e) {
return false;
}
}
public static boolean editMessage(IMessage message, String content) {
try {
return RequestBuffer.request(() -> {
try {
if (message != null && !message.isDeleted()) {
message.edit(content);
}
return true;
} catch (DiscordException | MissingPermissionsException e) {
//Failed to edit.
return false;
}
}).get();
} catch (NullPointerException e) {
return false;
}
}
public static boolean editMessage(IMessage message, String content, EmbedObject embed) {
try {
return RequestBuffer.request(() -> {
try {
if (!message.isDeleted()) {
message.edit(content, embed);
}
return true;
} catch (DiscordException | MissingPermissionsException e) {
//Failed to edit.
return false;
}
}).get();
} catch (NullPointerException e) {
return false;
}
}
}

View File

@@ -0,0 +1,81 @@
package com.cloudcraftgaming.discal.api.message;
import com.cloudcraftgaming.discal.api.file.ReadFile;
import com.cloudcraftgaming.discal.api.object.GuildSettings;
import com.cloudcraftgaming.discal.api.utils.MessageUtils;
import com.cloudcraftgaming.discal.logger.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
@SuppressWarnings("unchecked")
public class MessageManager {
private static Map<String, Map<String, String>> langs;
public static void loadLangs() {
langs = ReadFile.readAllLangFiles();
}
public static boolean reloadLangs() {
try {
langs = ReadFile.readAllLangFiles();
return true;
} catch (Exception e) {
Logger.getLogger().exception(null, "Failed to reload lang files!", e, MessageManager.class, true);
return false;
}
}
public static List<String> getLangs() {
return new ArrayList<>(langs.keySet());
}
public static boolean isSupported(String _value) {
for (String l : langs.keySet()) {
if (l.equalsIgnoreCase(_value)) {
return true;
}
}
return false;
}
public static String getValidLang(String _value) {
for (String l : langs.keySet()) {
if (l.equalsIgnoreCase(_value)) {
return l;
}
}
return "ENGLISH";
}
public static String getMessage(String key, GuildSettings settings) {
Map<String, String> messages;
if (settings.getLang() != null && langs.containsKey(settings.getLang())) {
messages = langs.get(settings.getLang());
} else {
messages = langs.get("ENGLISH");
}
return messages.getOrDefault(key, "***FAILSAFE MESSAGE*** MESSAGE NOT FOUND!! Message requested: " + key).replace("%lb%", MessageUtils.lineBreak);
}
public static String getMessage(String key, String var, String replace, GuildSettings settings) {
Map<String, String> messages;
if (settings.getLang() != null && langs.containsKey(settings.getLang())) {
messages = langs.get(settings.getLang());
} else {
messages = langs.get("ENGLISH");
}
return messages.getOrDefault(key, "***FAILSAFE MESSAGE*** MESSAGE NOT FOUND!! Message requested: " + key).replace(var, replace).replace("%lb%", MessageUtils.lineBreak);
}
}

View File

@@ -0,0 +1,78 @@
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;
import java.net.URI;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
public class CalendarMessageFormatter {
public static String getCalendarLink(String calId) {
URI callURI = URI.create(calId);
return "https://calendar.google.com/calendar/embed?src=" + callURI;
}
public static EmbedObject getCalendarLinkEmbed(Calendar cal, GuildSettings settings) {
EmbedBuilder em = new EmbedBuilder();
em.withAuthorIcon(DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL());
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(cal.getId()));
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().getClient().getGuildByID(266063520112574464L).getIconURL());
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);
} //No else needed, just don't post it.
em.withFooterText(MessageManager.getMessage("Embed.Calendar.Pre.Key", settings));
em.withColor(56, 138, 237);
return em.build();
}
}

View File

@@ -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.Message;
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<JsonNode> 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<CodeResponse>() {
}.getType();
CodeResponse cr = new Gson().fromJson(response.getBody().toString(), type);
//Send DM to user with code.
EmbedBuilder em = new EmbedBuilder();
em.withAuthorIcon(DisCalAPI.getAPI().getClient().getGuildByID(266063520112574464L).getIconURL());
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();
Message.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 {
Message.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();
Message.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<JsonNode> 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<AuthRefreshResponse>() {
}.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<JsonNode> 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
Message.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<AuthPollResponseError>() {
}.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")) {
Message.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Failure.Expired", settings), poll.getUser());
} else {
Message.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);
Message.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<AuthPollResponseGrant>() {
}.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));
DatabaseManager.getManager().updateSettings(gs);
try {
Calendar service = CalendarAuth.getCalendarService(gs);
List<CalendarListEntry> items = service.calendarList().list().setMinAccessRole("writer").execute().getItems();
Message.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().getClient().getGuildByID(266063520112574464L).getIconURL());
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(i.getId()));
em.withColor(56, 138, 237);
Message.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);
Message.sendDirectMessage(MessageManager.getMessage("AddCalendar.Auth.Poll.Failure.ListCalendars", settings), poll.getUser());
}
} else {
//Unknown network error...
Message.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);
Message.sendDirectMessage(MessageManager.getMessage("Notification.Error.Unknown", settings), poll.getUser());
}
}
}

View File

@@ -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());
}
}

View File

@@ -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) {
this.val = val;
}
}

View File

@@ -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 Integer maxCalendars;
private boolean twelveHour;
private boolean branded;
private final ArrayList<String> 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 Integer getMaxCalendars() {
return maxCalendars;
}
public boolean useTwelveHour() {
return twelveHour;
}
public boolean isBranded() {
return branded;
}
public ArrayList<String> getDmAnnouncements() {
return dmAnnouncements;
}
public String getDmAnnouncementsString() {
StringBuilder users = new StringBuilder();
Integer 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);
}
}

View File

@@ -0,0 +1,389 @@
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<String> subscriberRoleIds = new ArrayList<>();
private final ArrayList<String> 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<String> 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<String> 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() {
return type;
}
/**
* 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(Integer _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 <code>true</code> if all values are present, else <code>false</code>.
*/
public Boolean hasRequiredValues() {
return (minutesBefore != 0 || hoursBefore != 0) && !(type.equals(AnnouncementType.SPECIFIC) && eventId.equalsIgnoreCase("N/a")) && !announcementChannelId.equalsIgnoreCase("N/a");
}
}

View File

@@ -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;
}
}

View File

@@ -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 <code>true</code> if successful, else <code>false</code>.
*/
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;
}
}

View File

@@ -0,0 +1,60 @@
package com.cloudcraftgaming.discal.api.object.calendar;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
public class CalendarData {
private final long guildId;
private final Integer calendarNumber;
private String calendarId;
private String calendarAddress;
private boolean external;
public CalendarData(long _guildID, Integer _calendarNumber) {
guildId = _guildID;
calendarNumber = _calendarNumber;
calendarId = "primary";
calendarAddress = "primary";
external = false;
}
//Getters
public long getGuildId() {
return guildId;
}
public Integer getCalendarNumber() {
return calendarNumber;
}
public String getCalendarId() {
return calendarId;
}
public String getCalendarAddress() {
return calendarAddress;
}
public boolean isExternal() {
return external;
}
//Setters
public void setCalendarId(String _calendarId) {
calendarId = _calendarId;
}
public void setCalendarAddress(String _calendarAddress) {
calendarAddress = _calendarAddress;
}
public void setExternal(boolean _external) {
external = _external;
}
}

View File

@@ -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 <code>true</code> if required data set, otherwise <code>false</code>.
*/
public Boolean hasRequiredValues() {
return summary != null && timezone != null;
}
}

View File

@@ -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<String, String> 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<String, String> getSubCommands() {
return subCommands;
}
//Setters
public void setDescription(String _description) {
description = _description;
}
public void setExample(String _example) {
example = _example;
}
}

View File

@@ -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 <code>true</code> if successful, else <code>false</code>.
*/
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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,377 @@
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 {
if (settings.useExternalCalendar()) {
cal = CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute();
} else {
cal = CalendarAuth.getCalendarService().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 <code>true</code> if recurring, otherwise <code>false</code>.
*/
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 <code>true</code> if required values set, otherwise <code>false</code>.
*/
public Boolean hasRequiredValues() {
return startDateTime != null && endDateTime != null;
}
}

View File

@@ -0,0 +1,143 @@
package com.cloudcraftgaming.discal.api.object.event;
import com.cloudcraftgaming.discal.api.enums.event.EventFrequency;
import com.cloudcraftgaming.discal.api.utils.MessageUtils;
/**
* 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) {
//Infinite
return rrule;
} 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() + MessageUtils.lineBreak +
"Interval: " + interval;
if (count < 1) {
return humanRead + MessageUtils.lineBreak + "Amount: Infinite";
} else {
return humanRead + MessageUtils.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;
}
}

View File

@@ -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<String> goingOnTime = new ArrayList<>();
private final ArrayList<String> goingLate = new ArrayList<>();
private final ArrayList<String> notGoing = new ArrayList<>();
private final ArrayList<String> 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<String> getGoingOnTime() {
return goingOnTime;
}
public ArrayList<String> getGoingLate() {
return goingLate;
}
public ArrayList<String> getNotGoing() {
return notGoing;
}
public ArrayList<String> getUndecided() {
return undecided;
}
public String getGoingOnTimeString() {
StringBuilder goingString = new StringBuilder();
Integer 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();
Integer 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();
Integer 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();
Integer 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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,119 @@
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;
import java.net.URI;
/**
* 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://calendar.google.com/calendar/embed?src=" + URI.create(cd.getCalendarAddress());
external = cd.isExternal();
try {
if (cd.isExternal()) {
Calendar cal = CalendarAuth.getCalendarService(gs).calendars().get(id).execute();
name = cal.getSummary();
description = cal.getDescription();
timezone = cal.getTimeZone().replaceAll("/", "___");
} else {
Calendar cal = CalendarAuth.getCalendarService().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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<WebRole> roles = new ArrayList<>();
private List<WebChannel> channels = new ArrayList<>();
private List<Announcement> 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<WebRole> getRoles() {
return roles;
}
public List<WebChannel> getChannels() {
return channels;
}
public List<Announcement> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 <code>true</code> if the announcement exists, else <code>false</code>.
*/
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;
}
}

View File

@@ -0,0 +1,84 @@
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;
import java.io.IOException;
/**
* 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 <code>true</code> if successful, else <code>false</code>.
*/
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();
service.calendars().delete(data.getCalendarAddress()).execute();
}
} catch (IOException 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 {
if (settings.useExternalCalendar()) {
return CalendarAuth.getCalendarService(settings).calendars().get(data.getCalendarAddress()).execute() != null;
} else {
return CalendarAuth.getCalendarService().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;
}
}
}

View File

@@ -0,0 +1,100 @@
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 <code>true</code> if successfully deleted, otherwise <code>false</code>.
*/
public static Boolean deleteEvent(GuildSettings settings, String eventId) {
//TODO: Support multiple calendars...
String calendarId = DatabaseManager.getManager().getMainCalendar(settings.getGuildID()).getCalendarAddress();
try {
Calendar service;
if (settings.useExternalCalendar()) {
service = CalendarAuth.getCalendarService(settings);
} else {
service = CalendarAuth.getCalendarService();
}
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;
if (settings.useExternalCalendar()) {
service = CalendarAuth.getCalendarService(settings);
} else {
service = CalendarAuth.getCalendarService();
}
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;
}
public static String applyHoursToRawUserInput(String dateRaw, Integer plus) {
//format: yyyy/MM/dd-HH:mm:ss
String hoursS = dateRaw.substring(11, 13);
try {
Integer newHours = Integer.valueOf(hoursS);
newHours = newHours + plus;
String[] timeArray = dateRaw.split(":");
return timeArray[0] + newHours + ":" + timeArray[1] + ":" + timeArray[2];
} catch (NumberFormatException e) {
Logger.getLogger().exception(null, "Failed to convert to number from: " + hoursS, e, EventUtils.class, true);
}
return dateRaw;
}
}

View File

@@ -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.
* <br> <br>
* 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 <b>CLEARLY DEFINED</b> 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(), ">");
}
}

View File

@@ -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<WebGuild> getGuilds(String userId) {
List<WebGuild> 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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,10 @@
package com.cloudcraftgaming.discal.api.utils;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
public class MessageUtils {
public static String lineBreak = System.getProperty("line.separator");
}

View File

@@ -0,0 +1,145 @@
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 <code>true</code> if the user has the proper role, otherwise <code>false</code>.
*/
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 <code>true</code> if in correct channel, otherwise <code>false</code>.
*/
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);
}
}

View File

@@ -0,0 +1,138 @@
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 <code>true</code> if the date is in the past, otherwise <code>false</code>.
*/
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)) {
if (settings.useExternalCalendar()) {
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 external calendar auth", e, TimeUtils.class, true);
//Return false and allow RSVP so user is not adversely affected.
return false;
}
} else {
try {
Calendar service = CalendarAuth.getCalendarService();
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 <code>true</code> if the end is before the start, otherwise <code>false</code>.
*/
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 <code>true</code> of the start is after the end, otherwise <code>false</code>.
*/
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;
}
}

View File

@@ -0,0 +1,273 @@
package com.cloudcraftgaming.discal.logger;
import com.cloudcraftgaming.discal.api.DisCalAPI;
import com.cloudcraftgaming.discal.api.message.Message;
import com.cloudcraftgaming.discal.api.object.BotSettings;
import com.cloudcraftgaming.discal.api.utils.MessageUtils;
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(266063520112574464L);
IChannel channel = guild.getChannelByID(302249332244217856L);
Message.sendMessage(em.build(), "```" + shortError + "```", channel);
}
}
//ALWAYS LOG TO FILE!
try {
FileWriter exceptions = new FileWriter(exceptionsFile, true);
exceptions.write("ERROR --- " + timeStamp + " ---" + MessageUtils.lineBreak);
if (author != null) {
exceptions.write("user: " + author.getName() + "#" + author.getDiscriminator() + MessageUtils.lineBreak);
}
if (message != null) {
exceptions.write("message: " + message + MessageUtils.lineBreak);
}
exceptions.write(error + MessageUtils.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(266063520112574464L);
IChannel channel = guild.getChannelByID(302249332244217856L);
Message.sendMessage(em.build(), "```" + message + "```", channel);
}
}
//ALWAYS LOG TO FILE!
try {
FileWriter file = new FileWriter(debugFile, true);
file.write("DEBUG --- " + timeStamp + " ---" + MessageUtils.lineBreak);
if (author != null) {
file.write("user: " + author.getName() + "#" + author.getDiscriminator() + MessageUtils.lineBreak);
}
if (message != null) {
file.write("message: " + message + MessageUtils.lineBreak);
}
if (info != null) {
file.write("info: " + info + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
if (message != null) {
file.write("info: " + message + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
file.write("info: " + message + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
file.write("info: " + message + MessageUtils.lineBreak);
file.write("IP: " + ip + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
file.write("info: " + message + MessageUtils.lineBreak);
file.write("IP: " + ip + MessageUtils.lineBreak);
file.write("Host: " + host + MessageUtils.lineBreak);
file.write("Endpoint: " + endpoint + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
file.write("info: " + message + MessageUtils.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 + " ---" + MessageUtils.lineBreak);
file.write("info: " + message + MessageUtils.lineBreak);
file.write("guild Id: " + guildId + MessageUtils.lineBreak);
file.write("announcement Id: " + announcementId + MessageUtils.lineBreak);
file.write("event id: " + eventId + MessageUtils.lineBreak);
file.close();
} catch (IOException io) {
io.printStackTrace();
}
}
}