diff --git a/pom.xml b/pom.xml index 0949061fc..9c04f1e21 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,7 @@ UTF-8 UNKNOWN + bitly-access-token @@ -69,6 +70,17 @@ ${env.BUILD_NUMBER} + + bitly + + + env.BITLY_ACCESS_TOKEN + + + + ${env.BITLY_ACCESS_TOKEN} + + @@ -90,21 +102,44 @@ 1.4.1 + replace-bitly-access-token + generate-sources + + replace + + + ${project.build.sourceDirectory} + + com/onarandombox/MultiverseCore/utils/webpaste/BitlyURLShortener.java + + + + bitly-access-token + ${project.bitly-access-token} + + + + + + replace-maven-version-number prepare-package replace + + ${project.build.directory}/classes + + plugin.yml + + + + maven-version-number + ${project.version}-b${project.build.number} + + + - - target/classes/plugin.yml - - - maven-version-number - ${project.version}-b${project.build.number} - - - diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java index b2ac51e40..3f4b26f52 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/VersionCommand.java @@ -10,12 +10,13 @@ import com.dumptruckman.minecraft.util.Logging; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.event.MVVersionEvent; -import com.onarandombox.MultiverseCore.utils.webpaste.BitlyURLShortener; import com.onarandombox.MultiverseCore.utils.webpaste.PasteFailedException; import com.onarandombox.MultiverseCore.utils.webpaste.PasteService; import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceFactory; import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceType; import com.onarandombox.MultiverseCore.utils.webpaste.URLShortener; +import com.onarandombox.MultiverseCore.utils.webpaste.URLShortenerFactory; +import com.onarandombox.MultiverseCore.utils.webpaste.URLShortenerType; import com.pneumaticraft.commandhandler.CommandHandler; import org.apache.commons.lang.StringUtils; import org.bukkit.ChatColor; @@ -24,9 +25,12 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionDefault; import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.util.StringUtil; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,94 +39,89 @@ * Dumps version info to the console. */ public class VersionCommand extends MultiverseCommand { - private static final URLShortener SHORTENER = new BitlyURLShortener(); + private static final URLShortener SHORTENER = URLShortenerFactory.getService(URLShortenerType.BITLY); public VersionCommand(MultiverseCore plugin) { super(plugin); this.setName("Multiverse Version"); - this.setCommandUsage("/mv version " + ChatColor.GOLD + "-[bh] [--include-plugin-list]"); + this.setCommandUsage("/mv version " + ChatColor.GOLD + "-[bhp] [--include-plugin-list]"); this.setArgRange(0, 2); this.addKey("mv version"); this.addKey("mvv"); this.addKey("mvversion"); this.setPermission("multiverse.core.version", - "Dumps version info to the console, optionally to pastie.org with -p or pastebin.com with a -b.", PermissionDefault.TRUE); + "Dumps version info to the console, optionally to pastebin.com with -b, to hastebin.com using -h, or to paste.gg with -p.", PermissionDefault.TRUE); } private String getLegacyString() { - StringBuilder legacyFile = new StringBuilder(); - legacyFile.append("[Multiverse-Core] Multiverse-Core Version: ").append(this.plugin.getDescription().getVersion()).append('\n'); - legacyFile.append("[Multiverse-Core] Bukkit Version: ").append(this.plugin.getServer().getVersion()).append('\n'); - legacyFile.append("[Multiverse-Core] Loaded Worlds: ").append(this.plugin.getMVWorldManager().getMVWorlds()).append('\n'); - legacyFile.append("[Multiverse-Core] Multiverse Plugins Loaded: ").append(this.plugin.getPluginCount()).append('\n'); - legacyFile.append("[Multiverse-Core] Economy being used: ").append(plugin.getEconomist().getEconomyName()).append('\n'); - legacyFile.append("[Multiverse-Core] Permissions Plugin: ").append(this.plugin.getMVPerms().getType()).append('\n'); - legacyFile.append("[Multiverse-Core] Dumping Config Values: (version ") - .append(this.plugin.getMVConfig().getVersion()).append(")").append('\n'); - legacyFile.append("[Multiverse-Core] messagecooldown: ").append(plugin.getMessaging().getCooldown()).append('\n'); - legacyFile.append("[Multiverse-Core] teleportcooldown: ").append(plugin.getMVConfig().getTeleportCooldown()).append('\n'); - legacyFile.append("[Multiverse-Core] worldnameprefix: ").append(plugin.getMVConfig().getPrefixChat()).append('\n'); - legacyFile.append("[Multiverse-Core] worldnameprefixFormat: ").append(plugin.getMVConfig().getPrefixChatFormat()).append('\n'); - legacyFile.append("[Multiverse-Core] enforceaccess: ").append(plugin.getMVConfig().getEnforceAccess()).append('\n'); - legacyFile.append("[Multiverse-Core] displaypermerrors: ").append(plugin.getMVConfig().getDisplayPermErrors()).append('\n'); - legacyFile.append("[Multiverse-Core] teleportintercept: ").append(plugin.getMVConfig().getTeleportIntercept()).append('\n'); - legacyFile.append("[Multiverse-Core] firstspawnoverride: ").append(plugin.getMVConfig().getFirstSpawnOverride()).append('\n'); - legacyFile.append("[Multiverse-Core] firstspawnworld: ").append(plugin.getMVConfig().getFirstSpawnWorld()).append('\n'); - legacyFile.append("[Multiverse-Core] debug: ").append(plugin.getMVConfig().getGlobalDebug()).append('\n'); - legacyFile.append("[Multiverse-Core] Special Code: FRN002").append('\n'); - return legacyFile.toString(); + return "[Multiverse-Core] Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + System.lineSeparator() + + "[Multiverse-Core] Bukkit Version: " + this.plugin.getServer().getVersion() + System.lineSeparator() + + "[Multiverse-Core] Loaded Worlds: " + this.plugin.getMVWorldManager().getMVWorlds() + System.lineSeparator() + + "[Multiverse-Core] Multiverse Plugins Loaded: " + this.plugin.getPluginCount() + System.lineSeparator() + + "[Multiverse-Core] Economy being used: " + plugin.getEconomist().getEconomyName() + System.lineSeparator() + + "[Multiverse-Core] Permissions Plugin: " + this.plugin.getMVPerms().getType() + System.lineSeparator() + + "[Multiverse-Core] Dumping Config Values: (version " + this.plugin.getMVConfig().getVersion() + ")" + System.lineSeparator() + + "[Multiverse-Core] messagecooldown: " + plugin.getMessaging().getCooldown() + System.lineSeparator() + + "[Multiverse-Core] teleportcooldown: " + plugin.getMVConfig().getTeleportCooldown() + System.lineSeparator() + + "[Multiverse-Core] worldnameprefix: " + plugin.getMVConfig().getPrefixChat() + System.lineSeparator() + + "[Multiverse-Core] worldnameprefixFormat: " + plugin.getMVConfig().getPrefixChatFormat() + System.lineSeparator() + + "[Multiverse-Core] enforceaccess: " + plugin.getMVConfig().getEnforceAccess() + System.lineSeparator() + + "[Multiverse-Core] displaypermerrors: " + plugin.getMVConfig().getDisplayPermErrors() + System.lineSeparator() + + "[Multiverse-Core] teleportintercept: " + plugin.getMVConfig().getTeleportIntercept() + System.lineSeparator() + + "[Multiverse-Core] firstspawnoverride: " + plugin.getMVConfig().getFirstSpawnOverride() + System.lineSeparator() + + "[Multiverse-Core] firstspawnworld: " + plugin.getMVConfig().getFirstSpawnWorld() + System.lineSeparator() + + "[Multiverse-Core] debug: " + plugin.getMVConfig().getGlobalDebug() + System.lineSeparator() + + "[Multiverse-Core] Special Code: FRN002" + System.lineSeparator(); } private String getMarkdownString() { - StringBuilder markdownString = new StringBuilder(); - markdownString.append("# Multiverse-Core\n"); - markdownString.append("## Overview\n"); - markdownString.append("| Name | Value |\n"); - markdownString.append("| --- | --- |\n"); - markdownString.append("| Multiverse-Core Version | `").append(this.plugin.getDescription().getVersion()).append("` |\n"); - markdownString.append("| Bukkit Version | `").append(this.plugin.getServer().getVersion()).append("` |\n"); - //markdownString.append("| Loaded Worlds | `").append(this.plugin.getMVWorldManager().getMVWorlds()).append("` |\n"); - markdownString.append("| Multiverse Plugins Loaded | `").append(this.plugin.getPluginCount()).append("` |\n"); - markdownString.append("| Economy being used | `").append(plugin.getEconomist().getEconomyName()).append("` |\n"); - markdownString.append("| Permissions Plugin | `").append(this.plugin.getMVPerms().getType()).append("` |\n"); - markdownString.append("## Parsed Config\n"); - markdownString.append("These are what Multiverse thought the in-memory values of the config were.\n\n"); - markdownString.append("| Config Key | Value |\n"); - markdownString.append("| --- | --- |\n"); - markdownString.append("| version | `").append(this.plugin.getMVConfig().getVersion()).append("` |\n"); - markdownString.append("| messagecooldown | `").append(plugin.getMessaging().getCooldown()).append("` |\n"); - markdownString.append("| teleportcooldown | `").append(plugin.getMVConfig().getTeleportCooldown()).append("` |\n"); - markdownString.append("| worldnameprefix | `").append(plugin.getMVConfig().getPrefixChat()).append("` |\n"); - markdownString.append("| worldnameprefixFormat | `").append(plugin.getMVConfig().getPrefixChatFormat()).append("` |\n"); - markdownString.append("| enforceaccess | `").append(plugin.getMVConfig().getEnforceAccess()).append("` |\n"); - markdownString.append("| displaypermerrors | `").append(plugin.getMVConfig().getDisplayPermErrors()).append("` |\n"); - markdownString.append("| teleportintercept | `").append(plugin.getMVConfig().getTeleportIntercept()).append("` |\n"); - markdownString.append("| firstspawnoverride | `").append(plugin.getMVConfig().getFirstSpawnOverride()).append("` |\n"); - markdownString.append("| firstspawnworld | `").append(plugin.getMVConfig().getFirstSpawnWorld()).append("` |\n"); - markdownString.append("| debug | `").append(plugin.getMVConfig().getGlobalDebug()).append("` |\n"); - return markdownString.toString(); + return "# Multiverse-Core" + System.lineSeparator() + + "## Overview" + System.lineSeparator() + + "| Name | Value |" + System.lineSeparator() + + "| --- | --- |" + System.lineSeparator() + + "| Multiverse-Core Version | `" + this.plugin.getDescription().getVersion() + "` |" + System.lineSeparator() + + "| Bukkit Version | `" + this.plugin.getServer().getVersion() + "` |" + System.lineSeparator() + + "| Loaded Worlds | `" + this.plugin.getMVWorldManager().getMVWorlds() + "` |" + System.lineSeparator() + + "| Multiverse Plugins Loaded | `" + this.plugin.getPluginCount() + "` |" + System.lineSeparator() + + "| Economy being used | `" + plugin.getEconomist().getEconomyName() + "` |" + System.lineSeparator() + + "| Permissions Plugin | `" + this.plugin.getMVPerms().getType() + "` |" + System.lineSeparator() + + "## Parsed Config" + System.lineSeparator() + + "These are what Multiverse thought the in-memory values of the config were." + System.lineSeparator() + System.lineSeparator() + + "| Config Key | Value |" + System.lineSeparator() + + "| --- | --- |" + System.lineSeparator() + + "| version | `" + this.plugin.getMVConfig().getVersion() + "` |" + System.lineSeparator() + + "| messagecooldown | `" + plugin.getMessaging().getCooldown() + "` |" + System.lineSeparator() + + "| teleportcooldown | `" + plugin.getMVConfig().getTeleportCooldown() + "` |" + System.lineSeparator() + + "| worldnameprefix | `" + plugin.getMVConfig().getPrefixChat() + "` |" + System.lineSeparator() + + "| worldnameprefixFormat | `" + plugin.getMVConfig().getPrefixChatFormat() + "` |" + System.lineSeparator() + + "| enforceaccess | `" + plugin.getMVConfig().getEnforceAccess() + "` |" + System.lineSeparator() + + "| displaypermerrors | `" + plugin.getMVConfig().getDisplayPermErrors() + "` |" + System.lineSeparator() + + "| teleportintercept | `" + plugin.getMVConfig().getTeleportIntercept() + "` |" + System.lineSeparator() + + "| firstspawnoverride | `" + plugin.getMVConfig().getFirstSpawnOverride() + "` |" + System.lineSeparator() + + "| firstspawnworld | `" + plugin.getMVConfig().getFirstSpawnWorld() + "` |" + System.lineSeparator() + + "| debug | `" + plugin.getMVConfig().getGlobalDebug() + "` |" + System.lineSeparator(); } private String readFile(final String filename) { - String result; + StringBuilder result; try { FileReader reader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(reader); String line; - result = ""; + result = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { - result += line + '\n'; + result.append(line).append(System.lineSeparator()); } } catch (FileNotFoundException e) { Logging.severe("Unable to find %s. Here's the traceback: %s", filename, e.getMessage()); e.printStackTrace(); - result = String.format("ERROR: Could not load: %s", filename); + result = new StringBuilder(String.format("ERROR: Could not load: %s", filename)); } catch (IOException e) { Logging.severe("Something bad happend when reading %s. Here's the traceback: %s", filename, e.getMessage()); e.printStackTrace(); - result = String.format("ERROR: Could not load: %s", filename); + result = new StringBuilder(String.format("ERROR: Could not load: %s", filename)); } - return result; + return result.toString(); } private Map getVersionFiles() { @@ -135,7 +134,7 @@ private Map getVersionFiles() { File configFile = new File(this.plugin.getDataFolder(), "config.yml"); files.put(configFile.getName(), this.readFile(configFile.getAbsolutePath())); - // Add the config.yml + // Add the worlds.yml File worldConfig = new File(this.plugin.getDataFolder(), "worlds.yml"); files.put(worldConfig.getName(), this.readFile(worldConfig.getAbsolutePath())); return files; @@ -149,19 +148,20 @@ public void runCommand(final CommandSender sender, final List args) { } MVVersionEvent versionEvent = new MVVersionEvent(this.getLegacyString(), this.getVersionFiles()); - final Map files = this.getVersionFiles(); this.plugin.getServer().getPluginManager().callEvent(versionEvent); String versionInfo = versionEvent.getVersionInfo(); + Map files = versionEvent.getDetailedVersionInfo(); if (CommandHandler.hasFlag("--include-plugin-list", args)) { - versionInfo = versionInfo + "\nPlugins: " + getPluginList(); + versionInfo = versionInfo + System.lineSeparator() + "Plugins: " + getPluginList(); + files.put("plugins.txt", "Plugins: " + getPluginList()); } final String data = versionInfo; // log to console - String[] lines = data.split("\n"); + String[] lines = data.split(System.lineSeparator()); for (String line : lines) { if (!line.isEmpty()) { Logging.info(line); @@ -176,9 +176,15 @@ public void run() { if (CommandHandler.hasFlag("-b", args)) { // private post to pastebin pasteUrl = postToService(PasteServiceType.PASTEBIN, true, data, files); + } else if (CommandHandler.hasFlag("-g", args)) { + // private post to github + pasteUrl = postToService(PasteServiceType.GITHUB, true, data, files); } else if (CommandHandler.hasFlag("-h", args)) { - // private post to pastebin + // private post to hastebin pasteUrl = postToService(PasteServiceType.HASTEBIN, true, data, files); + } else if (CommandHandler.hasFlag("-p", args)) { + // private post to paste.gg + pasteUrl = postToService(PasteServiceType.PASTEGG, true, data, files); } else { return; } @@ -204,20 +210,25 @@ public void run() { * @param pasteFiles Map of filenames/contents of debug info. * @return URL of visible paste */ - private static String postToService(PasteServiceType type, boolean isPrivate, String pasteData, - Map pasteFiles) { + private static String postToService(PasteServiceType type, boolean isPrivate, String pasteData, Map pasteFiles) { PasteService ps = PasteServiceFactory.getService(type, isPrivate); + try { String result; if (ps.supportsMultiFile()) { - result = ps.postData(ps.encodeData(pasteFiles), ps.getPostURL()); + result = ps.postData(pasteFiles); } else { - result = ps.postData(ps.encodeData(pasteData), ps.getPostURL()); + result = ps.postData(pasteData); } - return SHORTENER.shorten(result); + + if (SHORTENER != null) return SHORTENER.shorten(result); + return result; } catch (PasteFailedException e) { - System.out.print(e); - return "Error posting to service"; + e.printStackTrace(); + return "Error posting to service."; + } catch (NullPointerException e) { + e.printStackTrace(); + return "That service isn't supported yet."; } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java b/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java index 43c1ddfc1..a63d7020a 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java +++ b/src/main/java/com/onarandombox/MultiverseCore/event/MVVersionEvent.java @@ -66,4 +66,13 @@ public Map getDetailedVersionInfo() { public void appendVersionInfo(String moreVersionInfo) { this.versionInfoBuilder.append(moreVersionInfo); } + + /** + * Adds a file to to the detailed version-info currently saved in this event. + * @param filename The name of the file. + * @param text The file's content. + */ + public void putDetailedVersionInfo(String filename, String text) { + this.detailedVersionInfo.put(filename, text); + } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/BitlyURLShortener.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/BitlyURLShortener.java index e700c2e32..96fadd226 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/BitlyURLShortener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/BitlyURLShortener.java @@ -1,19 +1,41 @@ package com.onarandombox.MultiverseCore.utils.webpaste; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + import java.io.IOException; +import java.util.Map; /** - * An {@link URLShortener} using {@code bit.ly}. + * A {@link URLShortener} using {@code bit.ly}. Requires an access token. */ -public class BitlyURLShortener extends HttpAPIClient implements URLShortener { - private static final String GENERIC_BITLY_REQUEST_FORMAT = "https://api-ssl.bitly.com/v3/shorten?format=txt&apiKey=%s&login=%s&longUrl=%s"; +class BitlyURLShortener extends URLShortener { + private static final String ACCESS_TOKEN = "Bearer bitly-access-token"; + private static final String BITLY_POST_REQUEST = "https://api-ssl.bitly.com/v4/shorten"; + + BitlyURLShortener() { + super(BITLY_POST_REQUEST, ACCESS_TOKEN); + if (ACCESS_TOKEN.endsWith("access-token")) throw new UnsupportedOperationException(); + } - // I think it's no problem that these are public - private static final String USERNAME = "multiverse2"; - private static final String API_KEY = "R_9dbff4862a3bc0c4218a7d78cc10d0e0"; + /** + * {@inheritDoc} + */ + @Override + String encodeData(String data) { + JSONObject json = new JSONObject(); + json.put("domain", "j.mp"); + json.put("long_url", data); + return json.toJSONString(); + } - public BitlyURLShortener() { - super(String.format(GENERIC_BITLY_REQUEST_FORMAT, API_KEY, USERNAME, "%s")); + /** + * {@inheritDoc} + */ + @Override + String encodeData(Map data) { + throw new UnsupportedOperationException(); } /** @@ -22,13 +44,11 @@ public BitlyURLShortener() { @Override public String shorten(String longUrl) { try { - String result = this.exec(longUrl); - if (!result.startsWith("http://j.mp/")) // ... then it's failed :/ - throw new IOException(result); - return result; - } catch (IOException e) { + String stringJSON = this.exec(encodeData(longUrl), ContentType.JSON); + return (String) ((JSONObject) new JSONParser().parse(stringJSON)).get("link"); + } catch (IOException | ParseException e) { e.printStackTrace(); - return longUrl; // sorry ... + return longUrl; } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GitHubPasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GitHubPasteService.java new file mode 100644 index 000000000..717ac3c4a --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GitHubPasteService.java @@ -0,0 +1,88 @@ +package com.onarandombox.MultiverseCore.utils.webpaste; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Pastes to {@code gist.github.com}. Requires an access token with the {@code gist} scope. + */ +class GitHubPasteService extends PasteService { + private final boolean isPrivate; + // this access token must have the "gist" scope + private static final String ACCESS_TOKEN = "token github-access-token"; + private static final String GITHUB_POST_REQUEST = "https://api.github.com/gists"; + + GitHubPasteService(boolean isPrivate) { + super(GITHUB_POST_REQUEST, ACCESS_TOKEN); + this.isPrivate = isPrivate; + if (ACCESS_TOKEN.endsWith("access-token")) throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + @Override + String encodeData(String data) { + Map mapData = new HashMap(); + mapData.put("multiverse.txt", data); + return this.encodeData(mapData); + } + + /** + * {@inheritDoc} + */ + @Override + String encodeData(Map files) { + JSONObject root = new JSONObject(); + root.put("description", "Multiverse-Core Debug Info"); + root.put("public", !this.isPrivate); + JSONObject fileList = new JSONObject(); + for (Map.Entry entry : files.entrySet()) { + JSONObject fileObject = new JSONObject(); + fileObject.put("content", entry.getValue()); + fileList.put(entry.getKey(), fileObject); + } + + root.put("files", fileList); + return root.toJSONString(); + } + + /** + * {@inheritDoc} + */ + @Override + public String postData(String data) throws PasteFailedException { + try { + String stringJSON = this.exec(encodeData(data), ContentType.JSON); + return (String) ((JSONObject) new JSONParser().parse(stringJSON)).get("html_url"); + } catch (IOException | ParseException e) { + throw new PasteFailedException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String postData(Map data) throws PasteFailedException { + try { + String stringJSON = this.exec(encodeData(data), ContentType.JSON); + return (String) ((JSONObject) new JSONParser().parse(stringJSON)).get("html_url"); + } catch (IOException | ParseException e) { + throw new PasteFailedException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean supportsMultiFile() { + return true; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GithubPasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GithubPasteService.java deleted file mode 100644 index 6d8409692..000000000 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/GithubPasteService.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.onarandombox.MultiverseCore.utils.webpaste; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.util.HashMap; -import java.util.Map; - -public class GithubPasteService implements PasteService { - - private final boolean isPrivate; - - public GithubPasteService(boolean isPrivate) { - this.isPrivate = isPrivate; - } - - @Override - public String encodeData(String data) { - Map mapData = new HashMap(); - mapData.put("multiverse.txt", data); - return this.encodeData(mapData); - } - - @Override - public String encodeData(Map files) { - JsonObject root = new JsonObject(); - root.add("description", new JsonPrimitive("Multiverse-Core Debug Info")); - root.add("public", new JsonPrimitive(!this.isPrivate)); - JsonObject fileList = new JsonObject(); - for (Map.Entry entry : files.entrySet()) - { - JsonObject fileObject = new JsonObject(); - fileObject.add("content", new JsonPrimitive(entry.getValue())); - fileList.add(entry.getKey(), fileObject); - } - root.add("files", fileList); - return root.toString(); - } - - @Override - public URL getPostURL() { - try { - return new URL("https://api.github.com/gists"); - //return new URL("http://jsonplaceholder.typicode.com/posts"); - } catch (MalformedURLException e) { - return null; // should never hit here - } - } - - @Override - public String postData(String encodedData, URL url) throws PasteFailedException { - OutputStreamWriter wr = null; - BufferedReader rd = null; - try { - URLConnection conn = url.openConnection(); - conn.setDoOutput(true); - wr = new OutputStreamWriter(conn.getOutputStream()); - wr.write(encodedData); - wr.flush(); - - rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); - String line; - String pastieUrl = ""; - //Pattern pastiePattern = this.getURLMatchingPattern(); - StringBuilder responseString = new StringBuilder(); - - while ((line = rd.readLine()) != null) { - responseString.append(line); - } - return new JsonParser().parse(responseString.toString()).getAsJsonObject().get("html_url").getAsString(); - } catch (Exception e) { - throw new PasteFailedException(e); - } finally { - if (wr != null) { - try { - wr.close(); - } catch (IOException ignore) { } - } - if (rd != null) { - try { - rd.close(); - } catch (IOException ignore) { } - } - } - } - - @Override - public boolean supportsMultiFile() { - return true; - } -} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HastebinPasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HastebinPasteService.java index 69438cfd7..46af2d29c 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HastebinPasteService.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HastebinPasteService.java @@ -1,79 +1,67 @@ package com.onarandombox.MultiverseCore.utils.webpaste; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; import java.util.Map; /** * Pastes to {@code hastebin.com}. */ -public class HastebinPasteService implements PasteService { +class HastebinPasteService extends PasteService { + private static final String HASTEBIN_POST_REQUEST = "https://hastebin.com/documents"; + HastebinPasteService() { + super(HASTEBIN_POST_REQUEST, null); + } + + /** + * {@inheritDoc} + */ @Override - public String encodeData(String data) { + String encodeData(String data) { return data; } + /** + * {@inheritDoc} + */ @Override - public String encodeData(Map data) { + String encodeData(Map data) { throw new UnsupportedOperationException(); } + /** + * {@inheritDoc} + */ @Override - public URL getPostURL() { + public String postData(String data) throws PasteFailedException { try { - return new URL("https://hastebin.com/documents"); - } catch (MalformedURLException e) { - return null; // should never hit here + String stringJSON = this.exec(encodeData(data), ContentType.PLAINTEXT); + return "https://hastebin.com/" + ((JSONObject) new JSONParser().parse(stringJSON)).get("key"); + } catch (IOException | ParseException e) { + throw new PasteFailedException(e); } } + /** + * {@inheritDoc} + */ @Override - public String postData(String encodedData, URL url) throws PasteFailedException { - OutputStreamWriter wr = null; - BufferedReader rd = null; + public String postData(Map data) throws PasteFailedException { try { - URLConnection conn = url.openConnection(); - conn.setDoOutput(true); - - wr = new OutputStreamWriter(conn.getOutputStream()); - rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); - - wr.write(encodedData); - wr.flush(); - - String line; - StringBuilder responseString = new StringBuilder(); - while ((line = rd.readLine()) != null) { - responseString.append(line); - } - String key = new JsonParser().parse(responseString.toString()).getAsJsonObject().get("key").getAsString(); - - return "https://hastebin.com/" + key; - } catch (Exception e) { + String stringJSON = this.exec(encodeData(data), ContentType.PLAINTEXT); + return "https://hastebin.com/" + ((JSONObject) new JSONParser().parse(stringJSON)).get("key"); + } catch (IOException | ParseException e) { throw new PasteFailedException(e); - } finally { - if (wr != null) { - try { - wr.close(); - } catch (IOException ignore) { } - } - if (rd != null) { - try { - rd.close(); - } catch (IOException ignore) { } - } } } + /** + * {@inheritDoc} + */ @Override public boolean supportsMultiFile() { return false; diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HttpAPIClient.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HttpAPIClient.java index 55d69c5c0..8e423fcce 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HttpAPIClient.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/HttpAPIClient.java @@ -1,50 +1,120 @@ package com.onarandombox.MultiverseCore.utils.webpaste; +import javax.net.ssl.HttpsURLConnection; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.net.URL; -import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.util.Map; /** * HTTP API-client. */ -public abstract class HttpAPIClient { +abstract class HttpAPIClient { /** - * The URL for this API-request. + * The URL for this API-request, and if necessary, the access token. + * If an access token is not necessary, it should be set to null. */ - protected final String urlFormat; + private final String url; + private final String accessToken; - public HttpAPIClient(String urlFormat) { - this.urlFormat = urlFormat; + /** + * Types of data that can be sent. + */ + enum ContentType { + JSON, + PLAINTEXT, + URLENCODED + } + + HttpAPIClient(String url, String accessToken) { + this.url = url; + this.accessToken = accessToken; } + /** + * Returns the HTTP Content-Type header that corresponds with each ContentType. + * @param type The type of data. + * @return The HTTP Content-Type header that corresponds with the type of data. + */ + private String getContentHeader(ContentType type) { + switch (type) { + case JSON: + return "application/json; charset=utf-8"; + case PLAINTEXT: + return "text/plain; charset=utf-8"; + case URLENCODED: + return "application/x-www-form-urlencoded; charset=utf-8"; + default: + throw new IllegalStateException("Unexpected value: " + type); + } + } + + /** + * Encode the given String data into a format suitable for transmission in an HTTP request. + * + * @param data The raw data to encode. + * @return A URL-encoded string. + */ + abstract String encodeData(String data); + + /** + * Encode the given Map data into a format suitable for transmission in an HTTP request. + * + * @param data The raw data to encode. + * @return A URL-encoded string. + */ + abstract String encodeData(Map data); + /** * Executes this API-Request. - * @param args Format-args. + * @param payload The data that will be sent. + * @param type The type of data that will be sent. * @return The result (as text). * @throws IOException When the I/O-operation failed. */ - protected final String exec(Object... args) throws IOException { + final String exec(String payload, ContentType type) throws IOException { + BufferedReader rd = null; + OutputStreamWriter wr = null; - URLConnection conn = new URL(String.format(this.urlFormat, args)).openConnection(); - conn.connect(); - StringBuilder ret = new StringBuilder(); - BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); - while (!reader.ready()); // wait until reader is ready, may not be necessary, SUPPRESS CHECKSTYLE: EmptyStatement + HttpsURLConnection conn = (HttpsURLConnection) new URL(this.url).openConnection(); + conn.setRequestMethod("POST"); + conn.setDoOutput(true); - while (reader.ready()) { - ret.append(reader.readLine()).append('\n'); - } + // we can receive anything! + conn.addRequestProperty("Accept", "*/*"); + // set a dummy User-Agent + conn.addRequestProperty("User-Agent", "placeholder"); + // this isn't required, but is technically correct + conn.addRequestProperty("Content-Type", getContentHeader(type)); + // only some API requests require an access token + if (this.accessToken != null) conn.addRequestProperty("Authorization", this.accessToken); + + wr = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8.newEncoder()); + wr.write(payload); + wr.flush(); + + String line; + StringBuilder responseString = new StringBuilder(); + // this has to be initialized AFTER the data has been flushed! + rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + + while ((line = rd.readLine()) != null) responseString.append(line); + return responseString.toString(); } finally { - if (reader != null) { + if (wr != null) { + try { + wr.close(); + } catch (IOException ignore) { } + } + if (rd != null) { try { - reader.close(); + rd.close(); } catch (IOException ignore) { } } } - return ret.toString(); } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteFailedException.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteFailedException.java index 85a803a4b..82792f499 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteFailedException.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteFailedException.java @@ -1,7 +1,7 @@ package com.onarandombox.MultiverseCore.utils.webpaste; /** - * Thrown when pasting failed. + * Thrown when pasting fails. */ public class PasteFailedException extends Exception { public PasteFailedException() { diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteGGPasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteGGPasteService.java new file mode 100644 index 000000000..179bba003 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteGGPasteService.java @@ -0,0 +1,90 @@ +package com.onarandombox.MultiverseCore.utils.webpaste; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Pastes to {@code paste.gg}. + */ +class PasteGGPasteService extends PasteService { + private final boolean isPrivate; + private static final String PASTEGG_POST_REQUEST = "https://api.paste.gg/v1/pastes"; + + PasteGGPasteService(boolean isPrivate) { + super(PASTEGG_POST_REQUEST, null); + this.isPrivate = isPrivate; + } + + /** + * {@inheritDoc} + */ + @Override + String encodeData(String data) { + Map mapData = new HashMap(); + mapData.put("multiverse.txt", data); + return this.encodeData(mapData); + } + + /** + * {@inheritDoc} + */ + @Override + String encodeData(Map files) { + JSONObject root = new JSONObject(); + root.put("name", "Multiverse-Core Debug Info"); + root.put("visibility", this.isPrivate ? "unlisted" : "public"); + JSONArray fileList = new JSONArray(); + for (Map.Entry entry : files.entrySet()) { + JSONObject fileObject = new JSONObject(); + JSONObject contentObject = new JSONObject(); + fileObject.put("name", entry.getKey()); + fileObject.put("content", contentObject); + contentObject.put("format", "text"); + contentObject.put("value", entry.getValue()); + fileList.add(fileObject); + } + + root.put("files", fileList); + return root.toJSONString(); + } + + /** + * {@inheritDoc} + */ + @Override + public String postData(String data) throws PasteFailedException { + try { + String stringJSON = this.exec(encodeData(data), ContentType.JSON); + return (String) ((JSONObject) ((JSONObject) new JSONParser().parse(stringJSON)).get("result")).get("id"); + } catch (IOException | ParseException e) { + throw new PasteFailedException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String postData(Map data) throws PasteFailedException { + try { + String stringJSON = this.exec(encodeData(data), ContentType.JSON); + return "https://paste.gg/" + ((JSONObject) ((JSONObject) new JSONParser().parse(stringJSON)).get("result")).get("id"); + } catch (IOException | ParseException e) { + throw new PasteFailedException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean supportsMultiFile() { + return true; + } +} diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteService.java index 403f5ab83..0c474c9e8 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteService.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteService.java @@ -1,63 +1,48 @@ package com.onarandombox.MultiverseCore.utils.webpaste; -import java.net.URL; import java.util.Map; /** - * An interface to a web-based text-pasting service. Classes implementing this - * interface should implement its methods to send data to an online text-sharing - * service, such as pastebin.com. Conventionally, a paste is accomplished by (given - * some PasteService instance ps): + * An interface to a web-based text-pasting service. Classes extending this + * should implement its methods to send data to an online text-sharing service, + * such as pastebin.com. Given some PasteService instance ps, a paste is accomplished by: * - * {@code ps.postData(ps.encodeData(someString), ps.getPostURL());} + * {@code ps.postData(someString);} * * Services that provide a distinction between "public" and "private" pastes - * should implement a custom constructor that specifies which kind the PasteService + * should implement a constructor that specifies which kind the PasteService * instance is submitting; an example of this is the PastebinPasteService class. */ -public interface PasteService { +public abstract class PasteService extends HttpAPIClient { + PasteService(String url, String accessToken) { + super(url, accessToken); + } /** - * Encode the given String data into a format suitable for transmission in an HTTP request. + * Post data to the Web. * - * @param data The raw data to encode. - * @return A URL-encoded string. - */ - String encodeData(String data); - - /** - * Encode the given Map data into a format suitable for transmission in an HTTP request. - * - * @param data The raw data to encode. - * @return A URL-encoded string. - */ - String encodeData(Map data); - - /** - * Get the URL to which this paste service sends new pastes. - * - * @return The URL that will be accessed to complete the paste. + * @param data A String to post to the web. + * @throws PasteFailedException When pasting/posting the data failed. + * @return The URL at which the new paste is visible. */ - URL getPostURL(); + public abstract String postData(String data) throws PasteFailedException; /** - * Post encoded data to the Web. + * Post data to the Web. * - * @param encodedData A URL-encoded String containing the full request to post to - * the given URL. Can be the result of calling #encodeData(). - * @param url The URL to which to paste. Can be the result of calling #getPostURL(). + * @param data A Map to post to the web. * @throws PasteFailedException When pasting/posting the data failed. * @return The URL at which the new paste is visible. */ - String postData(String encodedData, URL url) throws PasteFailedException; + public abstract String postData(Map data) throws PasteFailedException; /** * Does this service support uploading multiple files. * - * Newer services like gist support multi-file which allows us to upload configs - * in addition to the standard logs. + * Newer services like GitHub's Gist support multi-file pastes, + * which allows us to upload configs in addition to the standard logs. * * @return True if this service supports multiple file upload. */ - boolean supportsMultiFile(); + public abstract boolean supportsMultiFile(); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceFactory.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceFactory.java index df4fb8315..f6f63a1ce 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceFactory.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceFactory.java @@ -14,12 +14,14 @@ private PasteServiceFactory() { } */ public static PasteService getService(PasteServiceType type, boolean isPrivate) { switch(type) { + case PASTEGG: + return new PasteGGPasteService(isPrivate); case PASTEBIN: return new PastebinPasteService(isPrivate); case HASTEBIN: return new HastebinPasteService(); case GITHUB: - return new GithubPasteService(isPrivate); + return new GitHubPasteService(isPrivate); default: return null; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceType.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceType.java index 0bd93e635..09424c0b5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceType.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PasteServiceType.java @@ -7,6 +7,10 @@ * @see PasteServiceFactory */ public enum PasteServiceType { + /** + * @see PasteGGPasteService + */ + PASTEGG, /** * @see PastebinPasteService */ @@ -16,7 +20,7 @@ public enum PasteServiceType { */ HASTEBIN, /** - * @see GithubPasteService + * @see GitHubPasteService */ GITHUB } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PastebinPasteService.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PastebinPasteService.java index 3f06f612e..ce7a44532 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PastebinPasteService.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/PastebinPasteService.java @@ -1,24 +1,19 @@ package com.onarandombox.MultiverseCore.utils.webpaste; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; import java.net.URLEncoder; import java.util.Map; /** * Pastes to {@code pastebin.com}. */ -public class PastebinPasteService implements PasteService { +class PastebinPasteService extends PasteService { + private final boolean isPrivate; + private static final String PASTEBIN_POST_REQUEST = "https://pastebin.com/api/api_post.php"; - private boolean isPrivate; - - public PastebinPasteService(boolean isPrivate) { + PastebinPasteService(boolean isPrivate) { + super(PASTEBIN_POST_REQUEST, null); this.isPrivate = isPrivate; } @@ -26,11 +21,16 @@ public PastebinPasteService(boolean isPrivate) { * {@inheritDoc} */ @Override - public URL getPostURL() { + String encodeData(String data) { try { - return new URL("http://pastebin.com/api/api_post.php"); - } catch (MalformedURLException e) { - return null; // should never hit here + return URLEncoder.encode("api_dev_key", "UTF-8") + "=" + URLEncoder.encode("d61d68d31e8e0392b59b50b277411c71", "UTF-8") + + "&" + URLEncoder.encode("api_option", "UTF-8") + "=" + URLEncoder.encode("paste", "UTF-8") + + "&" + URLEncoder.encode("api_paste_code", "UTF-8") + "=" + URLEncoder.encode(data, "UTF-8") + + "&" + URLEncoder.encode("api_paste_private", "UTF-8") + "=" + URLEncoder.encode(this.isPrivate ? "1" : "0", "UTF-8") + + "&" + URLEncoder.encode("api_paste_format", "UTF-8") + "=" + URLEncoder.encode("yaml", "UTF-8") + + "&" + URLEncoder.encode("api_paste_name", "UTF-8") + "=" + URLEncoder.encode("Multiverse-Core Debug Info", "UTF-8"); + } catch (UnsupportedEncodingException e) { + return ""; // should never hit here } } @@ -38,61 +38,37 @@ public URL getPostURL() { * {@inheritDoc} */ @Override - public String encodeData(String data) { - try { - String encData = URLEncoder.encode("api_dev_key", "UTF-8") + "=" + URLEncoder.encode("d61d68d31e8e0392b59b50b277411c71", "UTF-8"); - encData += "&" + URLEncoder.encode("api_option", "UTF-8") + "=" + URLEncoder.encode("paste", "UTF-8"); - encData += "&" + URLEncoder.encode("api_paste_code", "UTF-8") + "=" + URLEncoder.encode(data, "UTF-8"); - encData += "&" + URLEncoder.encode("api_paste_private", "UTF-8") + "=" + URLEncoder.encode(this.isPrivate ? "1" : "0", "UTF-8"); - encData += "&" + URLEncoder.encode("api_paste_format", "UTF-8") + "=" + URLEncoder.encode("yaml", "UTF-8"); - return encData; - } catch (UnsupportedEncodingException e) { - return ""; // should never hit here - } + String encodeData(Map data) { + throw new UnsupportedOperationException(); } + /** + * {@inheritDoc} + */ @Override - public String encodeData(Map data) { - return null; + public String postData(String data) throws PasteFailedException { + try { + return this.exec(encodeData(data), ContentType.URLENCODED); + } catch (IOException e) { + throw new PasteFailedException(e); + } } /** * {@inheritDoc} */ @Override - public String postData(String encodedData, URL url) throws PasteFailedException { - OutputStreamWriter wr = null; - BufferedReader rd = null; + public String postData(Map data) throws PasteFailedException { try { - URLConnection conn = url.openConnection(); - conn.setDoOutput(true); - wr = new OutputStreamWriter(conn.getOutputStream()); - wr.write(encodedData); - wr.flush(); - - rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); - String line; - String pastebinUrl = ""; - while ((line = rd.readLine()) != null) { - pastebinUrl = line; - } - return pastebinUrl; - } catch (Exception e) { + return this.exec(encodeData(data), ContentType.URLENCODED); + } catch (IOException e) { throw new PasteFailedException(e); - } finally { - if (wr != null) { - try { - wr.close(); - } catch (IOException ignore) { } - } - if (rd != null) { - try { - rd.close(); - } catch (IOException ignore) { } - } } } + /** + * {@inheritDoc} + */ @Override public boolean supportsMultiFile() { return false; diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortener.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortener.java index 75d50f634..be3d61b18 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortener.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortener.java @@ -1,13 +1,23 @@ package com.onarandombox.MultiverseCore.utils.webpaste; /** - * URL-Shortener. + * An interface to a web-based URL Shortener. Classes extending this should + * implement its methods to shorten links using the service. Given some + * URLShortener instance us, a URL is shortened by: + * + * {@code us.shorten(longUrl);} + * + * An example of this, is the BitlyURLShortener. */ -public interface URLShortener { +public abstract class URLShortener extends HttpAPIClient { + URLShortener(String url, String accessToken) { + super(url, accessToken); + } + /** - * Shorten an URL. + * Shorten a URL. * @param longUrl The long form. * @return The shortened URL. */ - String shorten(String longUrl); + public abstract String shorten(String longUrl); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerFactory.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerFactory.java new file mode 100644 index 000000000..c0f3cafac --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerFactory.java @@ -0,0 +1,23 @@ +package com.onarandombox.MultiverseCore.utils.webpaste; + +/** + * Used to construct {@link URLShortener}s. + */ +public class URLShortenerFactory { + private URLShortenerFactory() { } + + /** + * Constructs a new {@link URLShortener}. + * @param type The {@link URLShortenerType}. + * @return The newly created {@link URLShortener}. + */ + public static URLShortener getService(URLShortenerType type) { + if (type == URLShortenerType.BITLY) { + try { + return new BitlyURLShortener(); + } catch (UnsupportedOperationException ignored) {} + } + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerType.java b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerType.java new file mode 100644 index 000000000..d2c809f51 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/webpaste/URLShortenerType.java @@ -0,0 +1,14 @@ +package com.onarandombox.MultiverseCore.utils.webpaste; + +/** + * An enum containing all known {@link URLShortener}s. + * + * @see URLShortener + * @see URLShortenerFactory + */ +public enum URLShortenerType { + /** + * @see BitlyURLShortener + */ + BITLY +}