Added support for version command to upload to gist.github.com

This commit is contained in:
Eric Stokes 2016-03-12 15:10:07 -07:00
parent 71ba31a0f4
commit 0e3848874a
9 changed files with 304 additions and 32 deletions

12
pom.xml
View File

@ -189,6 +189,7 @@
<include>com.dumptruckman.minecraft:buscript</include>
<include>org.mcstats.bukkit:metrics</include>
<include>com.dumptruckman.minecraft:Logging</include>
<include>org.codehaus.jettison:jettison</include>
</includes>
</artifactSet>
<relocations>
@ -216,6 +217,10 @@
<pattern>com.dumptruckman.minecraft.util.DebugLog</pattern>
<shadedPattern>com.onarandombox.MultiverseCore.utils.DebugFileLogger</shadedPattern>
</relocation>
<relocation>
<pattern>org.codehaus.jettison.json</pattern>
<shadedPattern>org.codehaus.jettison.json.multiverse</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
@ -334,6 +339,13 @@
</exclusions>
</dependency>
<!-- End of Logging Dependency -->
<!-- Start of JSON dependency -->
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<!-- End of JSON dependency -->
<!-- Start of Test Dependencies -->
<dependency>
<groupId>junit</groupId>

View File

@ -20,8 +20,12 @@ import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Dumps version info to the console.
@ -32,7 +36,7 @@ public class VersionCommand extends MultiverseCommand {
public VersionCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Multiverse Version");
this.setCommandUsage("/mv version " + ChatColor.GOLD + "-[pb]");
this.setCommandUsage("/mv version " + ChatColor.GOLD + "-[pbg]");
this.setArgRange(0, 1);
this.addKey("mv version");
this.addKey("mvv");
@ -41,6 +45,98 @@ public class VersionCommand extends MultiverseCommand {
"Dumps version info to the console, optionally to pastie.org with -p or pastebin.com with a -b.", 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();
}
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();
}
private String readFile(final String filename) {
String result;
try {
FileReader reader = new FileReader(filename);
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
result = "";
while ((line = bufferedReader.readLine()) != null) {
result += line + '\n';
}
} 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);
} 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);
}
return result;
}
private Map<String, String> getVersionFiles() {
Map<String, String> files = new HashMap<String, String>();
// Add the legacy file, but as markdown so it's readable
files.put("version.md", this.getMarkdownString());
// Add the config.yml
File configFile = new File(this.plugin.getDataFolder(), "config.yml");
files.put(configFile.getName(), this.readFile(configFile.getAbsolutePath()));
// Add the config.yml
File worldConfig = new File(this.plugin.getDataFolder(), "worlds.yml");
files.put(worldConfig.getName(), this.readFile(worldConfig.getAbsolutePath()));
return files;
}
@Override
public void runCommand(final CommandSender sender, final List<String> args) {
// Check if the command was sent from a Player.
@ -48,28 +144,8 @@ public class VersionCommand extends MultiverseCommand {
sender.sendMessage("Version info dumped to console. Please check your server logs.");
}
StringBuilder buffer = new StringBuilder();
buffer.append("[Multiverse-Core] Multiverse-Core Version: ").append(this.plugin.getDescription().getVersion()).append('\n');
buffer.append("[Multiverse-Core] Bukkit Version: ").append(this.plugin.getServer().getVersion()).append('\n');
buffer.append("[Multiverse-Core] Loaded Worlds: ").append(this.plugin.getMVWorldManager().getMVWorlds()).append('\n');
buffer.append("[Multiverse-Core] Multiverse Plugins Loaded: ").append(this.plugin.getPluginCount()).append('\n');
buffer.append("[Multiverse-Core] Economy being used: ").append(plugin.getEconomist().getEconomyName()).append('\n');
buffer.append("[Multiverse-Core] Permissions Plugin: ").append(this.plugin.getMVPerms().getType()).append('\n');
buffer.append("[Multiverse-Core] Dumping Config Values: (version ")
.append(this.plugin.getMVConfig().getVersion()).append(")").append('\n');
buffer.append("[Multiverse-Core] messagecooldown: ").append(plugin.getMessaging().getCooldown()).append('\n');
buffer.append("[Multiverse-Core] teleportcooldown: ").append(plugin.getMVConfig().getTeleportCooldown()).append('\n');
buffer.append("[Multiverse-Core] worldnameprefix: ").append(plugin.getMVConfig().getPrefixChat()).append('\n');
buffer.append("[Multiverse-Core] worldnameprefixFormat: ").append(plugin.getMVConfig().getPrefixChatFormat()).append('\n');
buffer.append("[Multiverse-Core] enforceaccess: ").append(plugin.getMVConfig().getEnforceAccess()).append('\n');
buffer.append("[Multiverse-Core] displaypermerrors: ").append(plugin.getMVConfig().getDisplayPermErrors()).append('\n');
buffer.append("[Multiverse-Core] teleportintercept: ").append(plugin.getMVConfig().getTeleportIntercept()).append('\n');
buffer.append("[Multiverse-Core] firstspawnoverride: ").append(plugin.getMVConfig().getFirstSpawnOverride()).append('\n');
buffer.append("[Multiverse-Core] firstspawnworld: ").append(plugin.getMVConfig().getFirstSpawnWorld()).append('\n');
buffer.append("[Multiverse-Core] debug: ").append(plugin.getMVConfig().getGlobalDebug()).append('\n');
buffer.append("[Multiverse-Core] Special Code: FRN002").append('\n');
MVVersionEvent versionEvent = new MVVersionEvent(buffer.toString());
MVVersionEvent versionEvent = new MVVersionEvent(this.getLegacyString(), this.getVersionFiles());
final Map<String, String> files = this.getVersionFiles();
this.plugin.getServer().getPluginManager().callEvent(versionEvent);
// log to console
@ -85,9 +161,14 @@ public class VersionCommand extends MultiverseCommand {
if (args.size() == 1) {
String pasteUrl;
if (args.get(0).equalsIgnoreCase("-p")) {
pasteUrl = postToService(PasteServiceType.PASTIE, true, data); // private post to pastie
// private post to pastie
pasteUrl = postToService(PasteServiceType.PASTIE, true, data, files);
} else if (args.get(0).equalsIgnoreCase("-b")) {
pasteUrl = postToService(PasteServiceType.PASTEBIN, true, data); // private post to pastie
// private post to pastebin
pasteUrl = postToService(PasteServiceType.PASTEBIN, true, data, files);
} else if (args.get(0).equalsIgnoreCase("-g")) {
// private post to github
pasteUrl = postToService(PasteServiceType.GITHUB, true, data, files);
} else {
return;
}
@ -102,14 +183,23 @@ public class VersionCommand extends MultiverseCommand {
/**
* Send the current contents of this.pasteBinBuffer to a web service.
*
* @param type Service type to send to
* @param isPrivate Should the paste be marked as private.
* @param type Service type to send paste data to.
* @param isPrivate Should the paste be marked as private.
* @param pasteData Legacy string only data to post to a service.
* @param pasteFiles Map of filenames/contents of debug info.
* @return URL of visible paste
*/
private static String postToService(PasteServiceType type, boolean isPrivate, String pasteData) {
private static String postToService(PasteServiceType type, boolean isPrivate, String pasteData,
Map<String, String> pasteFiles) {
PasteService ps = PasteServiceFactory.getService(type, isPrivate);
try {
return SHORTENER.shorten(ps.postData(ps.encodeData(pasteData), ps.getPostURL()));
String result;
if (ps.supportsMultiFile()) {
result = ps.postData(ps.encodeData(pasteFiles), ps.getPostURL());
} else {
result = ps.postData(ps.encodeData(pasteData), ps.getPostURL());
}
return SHORTENER.shorten(result);
} catch (PasteFailedException e) {
System.out.print(e);
return "Error posting to service";

View File

@ -3,15 +3,19 @@ package com.onarandombox.MultiverseCore.event;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.Map;
/**
* Called when somebody requests version information about Multiverse.
*/
public class MVVersionEvent extends Event {
private final StringBuilder versionInfoBuilder;
private final Map<String, String> detailedVersionInfo;
public MVVersionEvent(String versionInfo) {
this.versionInfoBuilder = new StringBuilder(versionInfo);
public MVVersionEvent(String legacyVersionInfo, Map<String, String> files) {
this.versionInfoBuilder = new StringBuilder(legacyVersionInfo);
this.detailedVersionInfo = files;
}
private static final HandlerList HANDLERS = new HandlerList();
@ -40,6 +44,21 @@ public class MVVersionEvent extends Event {
return this.versionInfoBuilder.toString();
}
/**
* Gets the key/value pair of the detailed version info.
*
* This information is used for advanced paste services that would prefer
* to get the information as several files. Examples include config.yml or
* portals.yml.
*
* The keys are filenames, the values are the contents of the files.
*
* @return The key value mapping of files and the contents of those files.
*/
public Map<String, String> getDetailedVersionInfo() {
return this.detailedVersionInfo;
}
/**
* Appends more version-info to the version-info currently saved in this event.
* @param moreVersionInfo The version-info to add. Should end with '\n'.

View File

@ -0,0 +1,105 @@
package com.onarandombox.MultiverseCore.utils.webpaste;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
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<String, String> mapData = new HashMap<String, String>();
mapData.put("multiverse.txt", data);
return this.encodeData(mapData);
}
@Override
public String encodeData(Map<String, String> files) {
JSONObject root = new JSONObject();
String result = "";
try {
root.put("description", "Multiverse-Core Debug Info");
root.put("public", !this.isPrivate);
JSONObject fileList = new JSONObject();
for (Map.Entry<String, String> entry : files.entrySet())
{
JSONObject fileObject = new JSONObject();
fileObject.put("content", entry.getValue());
fileList.put(entry.getKey(), fileObject);
}
root.put("files", fileList);
result = root.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
@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);
}
JSONObject response = new JSONObject(responseString.toString());
return response.get("html_url").toString();
} 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;
}
}

View File

@ -1,6 +1,7 @@
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
@ -24,6 +25,14 @@ public interface PasteService {
*/
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<String, String> data);
/**
* Get the URL to which this paste service sends new pastes.
*
@ -42,4 +51,13 @@ public interface PasteService {
*/
String postData(String encodedData, URL url) 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.
*
* @return True if this service supports multiple file upload.
*/
boolean supportsMultiFile();
}

View File

@ -18,6 +18,8 @@ public class PasteServiceFactory {
return new PastebinPasteService(isPrivate);
case PASTIE:
return new PastiePasteService(isPrivate);
case GITHUB:
return new GithubPasteService(isPrivate);
default:
return null;
}

View File

@ -14,5 +14,9 @@ public enum PasteServiceType {
/**
* @see PastiePasteService
*/
PASTIE
PASTIE,
/**
* @see GithubPasteService
*/
GITHUB
}

View File

@ -9,6 +9,7 @@ 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}.
@ -50,6 +51,11 @@ public class PastebinPasteService implements PasteService {
}
}
@Override
public String encodeData(Map<String, String> data) {
return null;
}
/**
* {@inheritDoc}
*/
@ -86,4 +92,9 @@ public class PastebinPasteService implements PasteService {
}
}
}
@Override
public boolean supportsMultiFile() {
return false;
}
}

View File

@ -9,6 +9,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -51,6 +52,11 @@ public class PastiePasteService implements PasteService {
}
}
@Override
public String encodeData(Map<String, String> data) {
return null;
}
/**
* {@inheritDoc}
*/
@ -93,6 +99,11 @@ public class PastiePasteService implements PasteService {
}
}
@Override
public boolean supportsMultiFile() {
return false;
}
private Pattern getURLMatchingPattern() {
if (this.isPrivate) {
return Pattern.compile(".*http://pastie.org/.*key=([0-9a-z]+).*");