diff --git a/Plugins/mineplex-google-sheets/pom.xml b/Plugins/mineplex-google-sheets/pom.xml
index 864b42200..9a70533c8 100644
--- a/Plugins/mineplex-google-sheets/pom.xml
+++ b/Plugins/mineplex-google-sheets/pom.xml
@@ -13,6 +13,12 @@
mineplex-google-sheets
+
+ com.googlecode.json-simple
+ json-simple
+ 1.1.1
+ compile
+
org.json
json
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/GoogleSheetController.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/GoogleSheetController.java
index 0c96d03b8..2d5e6becd 100644
--- a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/GoogleSheetController.java
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/GoogleSheetController.java
@@ -1,74 +1,28 @@
package mineplex.googlesheets;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
+import java.awt.*;
-import org.json.JSONObject;
+import mineplex.googlesheets.sheetparser.SheetProviderImpl;
+import mineplex.googlesheets.skinhelper.SkinHelperUI;
public class GoogleSheetController
{
- private static final int SLEEP_TIME = 1000;
- private static final String DATA_STORE_DIR = ".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files";
-
- public static void main(String[] args) throws InterruptedException
+ public static void main(String[] args)
{
- String sheetToRead = System.getProperty("sheet");
- SpreadsheetType[] types;
+ String module = System.getProperty("module");
- if (sheetToRead == null)
+ if (module == null || module.equalsIgnoreCase("sheetparser"))
{
- types = SpreadsheetType.values();
+ new SheetProviderImpl();
}
- else
+ else if (module.equalsIgnoreCase("skinhelper"))
{
- types = new SpreadsheetType[]{SpreadsheetType.valueOf(sheetToRead)};
- }
-
- System.out.println("Loading Sheet Provider");
- SheetProvider provider = new SheetProvider();
- System.out.println("Loaded Sheet Provider");
-
- for (SpreadsheetType type : types)
- {
- System.out.println("Sleeping...");
- Thread.sleep(SLEEP_TIME);
- System.out.println("Getting data for " + type.name() + " (" + type.getID() + ")");
-
- JSONObject object = provider.asJSONObject(type);
-
- System.out.println("Done");
- System.out.println("Saving to file...");
-
- File dir = new File(DATA_STORE_DIR);
- File file = new File(dir + File.separator + type.name() + ".json");
-
- if (!dir.exists())
+ EventQueue.invokeLater(() ->
{
- System.out.println("mkdir");
- dir.mkdirs();
- }
-
- try
- {
- System.out.println("Deleting");
- file.delete();
- System.out.println("new File");
- file.createNewFile();
-
- FileWriter writer = new FileWriter(file);
-
- System.out.println("Writing");
- writer.write(object.toString());
-
- System.out.println("Closing...");
- writer.close();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
+ SkinHelperUI frame = new SkinHelperUI();
+ frame.setVisible(true);
+ });
}
}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SpreadsheetType.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SpreadsheetType.java
index 665bf33fd..2b26b1815 100644
--- a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SpreadsheetType.java
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SpreadsheetType.java
@@ -19,7 +19,7 @@ public enum SpreadsheetType
_id = id;
}
- public String getID()
+ public String getId()
{
return _id;
}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SheetProvider.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProvider.java
similarity index 69%
rename from Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SheetProvider.java
rename to Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProvider.java
index 7d7859c49..bc2e3a811 100644
--- a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/SheetProvider.java
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProvider.java
@@ -1,11 +1,11 @@
-package mineplex.googlesheets;
+package mineplex.googlesheets.sheetparser;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,13 +28,19 @@ import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.Sheet;
import com.google.api.services.sheets.v4.model.Spreadsheet;
+import mineplex.googlesheets.SpreadsheetType;
+
+/**
+ * A provider class designed with the functionality to get data from a Google Spreadsheet.
+ * Then proceed to return this data within the context of a {@link JSONObject}.
+ */
public class SheetProvider
{
- /** Application name. */
+ /** Service name. */
private static final String APPLICATION_NAME = "Mineplex Google Sheets";
- /** Directory to store user credentials for this application. */
+ /** Directory to store user credentials for the service. */
private static final File DATA_STORE_DIR = new File(".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files");
/** Global instance of the {@link FileDataStoreFactory}. */
@@ -46,7 +52,8 @@ public class SheetProvider
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
- private static final List SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS);
+ /** List of all permissions that the service requires */
+ private static final List SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS);
private Sheets _service;
private Credential _credential;
@@ -81,9 +88,9 @@ public class SheetProvider
* Creates an authorized Credential object.
*
* @return an authorized Credential object.
- * @throws IOException
+ * @throws IOException If the Credential fails to authorise.
*/
- public Credential authorize() throws IOException
+ private Credential authorize() throws IOException
{
// Load client secrets.
InputStream in = new FileInputStream(DATA_STORE_DIR + File.separator + "client_secret.json");
@@ -91,28 +98,37 @@ public class SheetProvider
// 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");
- return credential;
+ return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
/**
* Build and return an authorized Sheets API client service.
*
* @return an authorized Sheets API client service
- * @throws IOException
*/
- public Sheets getSheetsService()
+ private Sheets getSheetsService()
{
return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, _credential).setApplicationName(APPLICATION_NAME).build();
}
+ /**
+ * Returns the data comprised inside a Google Spreadsheet in the context of a {@link JSONObject}.
+ *
+ * @param spreadsheet The {@link SpreadsheetType} that you need to get the data from.
+ * @return A {@link JSONObject} containing all the data about a spreadsheet mapped by sheet -> rows -> columns.
+ */
public JSONObject asJSONObject(SpreadsheetType spreadsheet)
{
JSONObject parent = new JSONObject();
JSONArray array = new JSONArray();
Map>> valuesMap = get(spreadsheet);
-
- for (String sheetName : valuesMap.keySet())
+
+ if (valuesMap == null)
+ {
+ return null;
+ }
+
+ valuesMap.forEach((sheetName, lists) ->
{
List> values = valuesMap.get(sheetName);
@@ -122,20 +138,21 @@ public class SheetProvider
object.put("values", values);
array.put(object);
- }
+ });
parent.put("data", array);
return parent;
}
-
- public Map>> get(SpreadsheetType spreadsheet)
+
+ private Map>> get(SpreadsheetType spreadsheet)
{
try
{
- Spreadsheet googleSpreadsheet = _service.spreadsheets().get(spreadsheet.getID()).execute();
- Map>> valuesMap = new HashMap<>(googleSpreadsheet.getSheets().size() - 1);
+ Spreadsheet googleSpreadsheet = _service.spreadsheets().get(spreadsheet.getId()).execute();
+ List sheets = googleSpreadsheet.getSheets();
+ Map>> valuesMap = new HashMap<>(sheets.size());
- for (Sheet sheet : googleSpreadsheet.getSheets())
+ for (Sheet sheet : sheets)
{
String name = sheet.getProperties().getTitle();
@@ -152,9 +169,9 @@ public class SheetProvider
return null;
}
- public List> get(SpreadsheetType spreadsheet, String sheetName) throws IOException
+ private List> get(SpreadsheetType spreadsheet, String sheetName) throws IOException
{
- return _service.spreadsheets().values().get(spreadsheet.getID(), sheetName).execute().getValues();
+ return _service.spreadsheets().values().get(spreadsheet.getId(), sheetName).execute().getValues();
}
}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProviderImpl.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProviderImpl.java
new file mode 100644
index 000000000..36618657a
--- /dev/null
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/sheetparser/SheetProviderImpl.java
@@ -0,0 +1,82 @@
+package mineplex.googlesheets.sheetparser;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.json.JSONObject;
+
+import mineplex.googlesheets.SpreadsheetType;
+
+public class SheetProviderImpl
+{
+
+ private static final int SLEEP_TIME = 1000;
+ private static final String DATA_STORE_DIR = ".." + File.separatorChar + ".." + File.separatorChar + "update" + File.separatorChar + "files";
+
+ public SheetProviderImpl()
+ {
+ String sheetToRead = System.getProperty("sheet");
+ SpreadsheetType[] types;
+
+ if (sheetToRead == null)
+ {
+ types = SpreadsheetType.values();
+ }
+ else
+ {
+ types = new SpreadsheetType[]{SpreadsheetType.valueOf(sheetToRead)};
+ }
+
+ System.out.println("Loading Sheet Provider");
+ SheetProvider provider = new SheetProvider();
+ System.out.println("Loaded Sheet Provider");
+
+ for (SpreadsheetType type : types)
+ {
+ System.out.println("Sleeping...");
+ try
+ {
+ Thread.sleep(SLEEP_TIME);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ System.out.println("Getting data for " + type.name() + " (" + type.getId() + ")");
+
+ JSONObject object = provider.asJSONObject(type);
+
+ System.out.println("Done");
+ System.out.println("Saving to file...");
+
+ File dir = new File(DATA_STORE_DIR);
+ File file = new File(dir + File.separator + type.name() + ".json");
+
+ if (!dir.exists())
+ {
+ dir.mkdirs();
+ }
+
+ try
+ {
+ System.out.println("Deleting");
+ file.delete();
+ System.out.println("Creating a new file");
+ file.createNewFile();
+
+ FileWriter writer = new FileWriter(file);
+
+ System.out.println("Writing");
+ writer.write(object.toString());
+
+ System.out.println("Closing...");
+ writer.close();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/skinhelper/SkinHelperUI.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/skinhelper/SkinHelperUI.java
new file mode 100644
index 000000000..5994e634c
--- /dev/null
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/skinhelper/SkinHelperUI.java
@@ -0,0 +1,115 @@
+package mineplex.googlesheets.skinhelper;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.concurrent.TimeUnit;
+
+import mineplex.googlesheets.util.SkinFetcher;
+import mineplex.googlesheets.util.UUIDFetcher;
+
+public class SkinHelperUI extends JFrame
+{
+
+ private static final Font FONT = new Font("Verdana", Font.PLAIN, 12);
+ private static final long FETCH_WAIT_TIME = 30;
+ private static final long FETCH_WAIT_MILLISECONDS = TimeUnit.SECONDS.toMillis(FETCH_WAIT_TIME);
+
+ private long _lastFetch;
+
+ public SkinHelperUI()
+ {
+ setTitle("Skin Helper");
+ setResizable(false);
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ setBounds(100, 100, 150, 300);
+ JPanel contentPane = new JPanel();
+ contentPane.setBackground(Color.DARK_GRAY);
+ contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
+ setContentPane(contentPane);
+ contentPane.setLayout(null);
+
+ JTextField txtMinecraftName = new JTextField();
+ txtMinecraftName.setFont(FONT);
+ txtMinecraftName.setForeground(Color.WHITE);
+ txtMinecraftName.setBackground(Color.GRAY);
+ txtMinecraftName.setBounds(10, 55, 124, 20);
+ txtMinecraftName.setColumns(10);
+ contentPane.add(txtMinecraftName);
+
+ JLabel lblMinecraftName = new JLabel("Minecraft Name");
+ lblMinecraftName.setForeground(Color.WHITE);
+ lblMinecraftName.setFont(FONT);
+ lblMinecraftName.setBounds(10, 30, 100, 14);
+ contentPane.add(lblMinecraftName);
+
+ JButton btnOk = new JButton("OK");
+ btnOk.setForeground(Color.WHITE);
+ btnOk.setBackground(Color.DARK_GRAY);
+ btnOk.setBounds(10, 86, 124, 23);
+ contentPane.add(btnOk);
+
+ JLabel lblSkinValue = new JLabel("Skin Value");
+ lblSkinValue.setForeground(Color.WHITE);
+ lblSkinValue.setFont(FONT);
+ lblSkinValue.setBounds(10, 120, 100, 14);
+ contentPane.add(lblSkinValue);
+
+ JTextField txtSkinValue = new JTextField();
+ txtSkinValue.setEditable(false);
+ txtSkinValue.setForeground(Color.WHITE);
+ txtSkinValue.setBackground(Color.GRAY);
+ txtSkinValue.setFont(FONT);
+ txtSkinValue.setColumns(10);
+ txtSkinValue.setBounds(10, 145, 124, 20);
+ contentPane.add(txtSkinValue);
+
+ JLabel lblSkinSignature = new JLabel("Skin Signature");
+ lblSkinSignature.setForeground(Color.WHITE);
+ lblSkinSignature.setFont(FONT);
+ lblSkinSignature.setBounds(10, 176, 100, 14);
+ contentPane.add(lblSkinSignature);
+
+ JTextField txtSkinSignature = new JTextField();
+ txtSkinSignature.setEditable(false);
+ txtSkinSignature.setForeground(Color.WHITE);
+ txtSkinSignature.setBackground(Color.GRAY);
+ txtSkinSignature.setFont(FONT);
+ txtSkinSignature.setColumns(10);
+ txtSkinSignature.setBounds(10, 201, 124, 20);
+ contentPane.add(txtSkinSignature);
+
+ btnOk.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent event)
+ {
+ if (System.currentTimeMillis() - _lastFetch < FETCH_WAIT_MILLISECONDS)
+ {
+ JOptionPane.showMessageDialog(SkinHelperUI.this, "You must wait a minimum of " + FETCH_WAIT_TIME + " seconds between each skin fetch to prevent you from being blocked from using the Mojang API.");
+ return;
+ }
+
+ txtSkinValue.setText("Fetching...");
+ txtSkinSignature.setText(txtSkinValue.getText());
+
+ try
+ {
+ String[] skinData = SkinFetcher.getSkinData(UUIDFetcher.getPlayerUUIDNoDashes(txtMinecraftName.getText()));
+
+ txtSkinValue.setText(skinData[0]);
+ txtSkinSignature.setText(skinData[1]);
+
+ _lastFetch = System.currentTimeMillis();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ JOptionPane.showMessageDialog(SkinHelperUI.this, "Please check the Minecraft Name you have entered. If it is correct please wait a minute and try again.");
+ }
+ }
+ });
+ }
+}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/SkinFetcher.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/SkinFetcher.java
new file mode 100644
index 000000000..a8bdf6666
--- /dev/null
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/SkinFetcher.java
@@ -0,0 +1,42 @@
+package mineplex.googlesheets.util;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+public class SkinFetcher
+{
+
+ private static final String SKIN_URL = "https://sessionserver.mojang.com/session/minecraft/profile/UUID?unsigned=false";
+
+ public static String[] getSkinData(String uuid) throws Exception
+ {
+ String[] skinData = new String[2];
+ JSONObject object = UtilJSON.getFromURL(SKIN_URL.replaceFirst("UUID", uuid));
+ JSONArray properties = (JSONArray) object.get("properties");
+
+ System.out.println(properties.size());
+
+ for (Object o : properties)
+ {
+ System.out.println(o.toString());
+ }
+
+ JSONObject innerObject = (JSONObject) properties.get(0);
+
+ System.out.println(innerObject.size());
+
+ for (Object o : innerObject.entrySet())
+ {
+ System.out.println(o.toString());
+ }
+
+ skinData[1] = (String) innerObject.get("signature");
+ skinData[0] = (String) innerObject.get("value");
+
+ System.out.println(skinData[0]);
+ System.out.println(skinData[1]);
+
+ return skinData;
+ }
+
+}
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UUIDFetcher.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UUIDFetcher.java
new file mode 100644
index 000000000..92c50787b
--- /dev/null
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UUIDFetcher.java
@@ -0,0 +1,62 @@
+package mineplex.googlesheets.util;
+
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+
+/**
+ * A utility to fetch UUIDs based on a player's name.
+ * Adapted from UUIDFetcher inside Core.Common.
+ */
+public class UUIDFetcher
+{
+
+ private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
+ private static final JSONParser PARSER = new JSONParser();
+
+ public static String getPlayerUUIDNoDashes(String name) throws Exception
+ {
+ String uuid = null;
+ List nameList = Collections.singletonList(name);
+
+ HttpURLConnection connection = createConnection();
+ String body = JSONArray.toJSONString(nameList);
+ writeBody(connection, body);
+ JSONArray array = (JSONArray) PARSER.parse(new InputStreamReader(connection.getInputStream()));
+
+ for (Object profile : array)
+ {
+ JSONObject jsonProfile = (JSONObject) profile;
+ uuid = (String) jsonProfile.get("id");
+ }
+
+ return uuid;
+ }
+
+ private static void writeBody(HttpURLConnection connection, String body) throws Exception
+ {
+ OutputStream stream = connection.getOutputStream();
+ stream.write(body.getBytes());
+ stream.flush();
+ stream.close();
+ }
+
+ private static HttpURLConnection createConnection() throws Exception
+ {
+ URL url = new URL(PROFILE_URL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json");
+ connection.setUseCaches(false);
+ connection.setDoInput(true);
+ connection.setDoOutput(true);
+ return connection;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UtilJSON.java b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UtilJSON.java
new file mode 100644
index 000000000..5488d3217
--- /dev/null
+++ b/Plugins/mineplex-google-sheets/src/mineplex/googlesheets/util/UtilJSON.java
@@ -0,0 +1,41 @@
+package mineplex.googlesheets.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.nio.charset.Charset;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
+public class UtilJSON
+{
+
+ private static final JSONParser PARSER = new JSONParser();
+
+ private static String readAll(Reader rd) throws IOException
+ {
+ StringBuilder sb = new StringBuilder();
+ int cp;
+ while ((cp = rd.read()) != -1)
+ {
+ sb.append((char) cp);
+ }
+ return sb.toString();
+ }
+
+ public static JSONObject getFromURL(String url) throws IOException, ParseException
+ {
+ try (InputStream is = new URL(url).openStream())
+ {
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
+ String jsonText = readAll(rd);
+ return (JSONObject) PARSER.parse(jsonText);
+ }
+ }
+
+}