Switch from hastebin to pastes.dev and fix non multi-file services

This commit is contained in:
zax71 2023-08-28 14:38:42 +01:00
parent e06536acd6
commit 5af06d9a0f
5 changed files with 84 additions and 72 deletions

View File

@ -1,8 +1,6 @@
package com.onarandombox.MultiverseCore.commands; package com.onarandombox.MultiverseCore.commands;
import co.aikar.commands.CommandIssuer; import co.aikar.commands.CommandIssuer;
import co.aikar.commands.CommandManager;
import co.aikar.commands.MessageType;
import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.CommandPermission;
@ -10,7 +8,6 @@ import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand; import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Syntax;
import co.aikar.locales.MessageKeyProvider;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MVWorldManager;
@ -28,7 +25,6 @@ import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceFactory;
import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceType; import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceType;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -63,11 +59,8 @@ public class DumpsCommand extends MultiverseCommand {
.add(CommandFlag.builder("--pastebincom") .add(CommandFlag.builder("--pastebincom")
.addAlias("-b") .addAlias("-b")
.build()) .build())
.add(CommandFlag.builder("--github") .add(CommandFlag.builder("--pastesdev")
.addAlias("-g") .addAlias("-d")
.build())
.add(CommandFlag.builder("--hastebin")
.addAlias("-h")
.build()) .build())
.add(CommandFlag.builder("--pastegg") .add(CommandFlag.builder("--pastegg")
.addAlias("-p") .addAlias("-p")
@ -84,12 +77,12 @@ public class DumpsCommand extends MultiverseCommand {
@Subcommand("dumps") @Subcommand("dumps")
@CommandPermission("multiverse.core.dumps") @CommandPermission("multiverse.core.dumps")
@CommandCompletion("@flags:groupName=mvdumps") @CommandCompletion("@flags:groupName=mvdumps")
@Syntax("--pastebincom --hastebin --pastegg --logs --exclude-plugin-list") @Syntax("--pastebincom --pastesdev --pastegg --logs --exclude-plugin-list")
@Description("{@@mv-core.dumps.description}") @Description("{@@mv-core.dumps.description}")
public void onDumpsCommand(CommandIssuer issuer, public void onDumpsCommand(CommandIssuer issuer,
@Optional @Optional
@Syntax("--pastebincom --hastebin --pastegg --logs --exclude-plugin-list") @Syntax("--pastebincom --pastesdev --pastegg --logs --exclude-plugin-list")
@Description("{@@mv-core.dumps.flags.description}") @Description("{@@mv-core.dumps.flags.description}")
String[] flags String[] flags
) { ) {
@ -100,8 +93,6 @@ public class DumpsCommand extends MultiverseCommand {
this.addDebugInfoToEvent(versionEvent); this.addDebugInfoToEvent(versionEvent);
plugin.getServer().getPluginManager().callEvent(versionEvent); plugin.getServer().getPluginManager().callEvent(versionEvent);
final String versionInfo = versionEvent.getVersionInfo();
if (!parsedFlags.hasFlag("--exclude-plugin-list")) { if (!parsedFlags.hasFlag("--exclude-plugin-list")) {
versionEvent.putDetailedVersionInfo("plugins.md", "# Plugins\n\n" + getPluginList()); versionEvent.putDetailedVersionInfo("plugins.md", "# Plugins\n\n" + getPluginList());
} }
@ -117,13 +108,13 @@ public class DumpsCommand extends MultiverseCommand {
if (parsedFlags.hasFlag("--pastebincom")) { if (parsedFlags.hasFlag("--pastebincom")) {
hasArgs = true; hasArgs = true;
issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "https://pastebin.com"); issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "https://pastebin.com");
pasteURLs.put("pastebin.com", postToService(PasteServiceType.PASTEBIN, true, versionInfo, files)); pasteURLs.put("pastebin.com", postToService(PasteServiceType.PASTEBIN, true, null, files));
} }
if (parsedFlags.hasFlag("--hastebin")) { if (parsedFlags.hasFlag("--pastesdev")) {
hasArgs = true; hasArgs = true;
issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "need to yeet"); //TODO yeet it issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "https://pastes.dev");
pasteURLs.put("hastebin.com", postToService(PasteServiceType.HASTEBIN, true, versionInfo, files)); pasteURLs.put("pastes.dev", postToService(PasteServiceType.PASTESDEV, true, null, files));
} }
if (parsedFlags.hasFlag("--logs")) { if (parsedFlags.hasFlag("--logs")) {
@ -138,7 +129,6 @@ public class DumpsCommand extends MultiverseCommand {
try { try {
logs = Files.readString(logsPath); logs = Files.readString(logsPath);
} catch (IOException e) { } catch (IOException e) {
logs = "Could not read logs/latest.log";
Logging.warning("Could not read logs/latest.log"); Logging.warning("Could not read logs/latest.log");
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -149,7 +139,7 @@ public class DumpsCommand extends MultiverseCommand {
// Fallback to paste.gg if no other sites where specified // Fallback to paste.gg if no other sites where specified
if (parsedFlags.hasFlag("--pastegg") || !hasArgs) { if (parsedFlags.hasFlag("--pastegg") || !hasArgs) {
issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "https://paste.gg"); issuer.sendInfo(MVCorei18n.DUMPS_UPLOADING, "{link}", "https://paste.gg");
pasteURLs.put("paste.gg", postToService(PasteServiceType.PASTEGG, true, versionInfo, files)); pasteURLs.put("paste.gg", postToService(PasteServiceType.PASTEGG, true, null, files));
} }
// Finally, loop through and print all URLs // Finally, loop through and print all URLs
@ -206,27 +196,56 @@ public class DumpsCommand extends MultiverseCommand {
return " - " + StringUtils.join(plugin.getServer().getPluginManager().getPlugins(), "\n - "); return " - " + StringUtils.join(plugin.getServer().getPluginManager().getPlugins(), "\n - ");
} }
/**
* Turns a list of files in to a string containing askii art
* @param files Map of filenames/contents
* @return The askii art
*/
private String encodeAsString(Map<String, String> files) {
StringBuilder uploadData = new StringBuilder();
for (String file : files.keySet()) {
String data = files.get(file);
uploadData.append("# ---------- ")
.append(file)
.append(" ----------\n\n")
.append(data)
.append("\n\n");
}
return uploadData.toString();
}
/** /**
* Send the current contents of this.pasteBinBuffer to a web service. * Send the current contents of this.pasteBinBuffer to a web service.
* *
* @param type Service type to send paste data to. * @param type Service type to send paste data to.
* @param isPrivate Should the paste be marked as private. * @param isPrivate Should the paste be marked as private.
* @param pasteData Legacy string only data to post to a service. * @param rawPasteData Legacy string containing only data to post to a service.
* @param pasteFiles Map of filenames/contents of debug info. * @param pasteFiles Map of filenames/contents of debug info.
* @return URL of visible paste * @return URL of visible paste
*/ */
private static String postToService(PasteServiceType type, boolean isPrivate, @Nullable String pasteData, @Nullable Map<String, String> pasteFiles) { private String postToService(@NotNull PasteServiceType type, boolean isPrivate, @Nullable String rawPasteData, @Nullable Map<String, String> pasteFiles) {
PasteService pasteService = PasteServiceFactory.getService(type, isPrivate); PasteService pasteService = PasteServiceFactory.getService(type, isPrivate);
try { try {
String result; // Upload normally when multi file is supported
if (pasteService.supportsMultiFile()) { if (pasteService.supportsMultiFile()) {
result = pasteService.postData(pasteFiles); return pasteService.postData(pasteFiles);
} else {
result = pasteService.postData(pasteData);
} }
return result; // When there is raw paste data, use that
if (rawPasteData != null) { // For the logs
return pasteService.postData(rawPasteData);
}
// If all we have are files and the paste service does not support multi file then encode them
if (pasteFiles != null) {
return pasteService.postData(this.encodeAsString(pasteFiles));
}
// Should never get here
return "No data specified in code";
} catch (PasteFailedException e) { } catch (PasteFailedException e) {
e.printStackTrace(); e.printStackTrace();
return "Error posting to service."; return "Error posting to service.";

View File

@ -26,6 +26,7 @@ abstract class HttpAPIClient {
enum ContentType { enum ContentType {
JSON, JSON,
PLAINTEXT, PLAINTEXT,
PLAINTEXT_YAML,
URLENCODED URLENCODED
} }
@ -44,16 +45,13 @@ abstract class HttpAPIClient {
* @return The HTTP Content-Type header that corresponds with the type of data. * @return The HTTP Content-Type header that corresponds with the type of data.
*/ */
private String getContentHeader(ContentType type) { private String getContentHeader(ContentType type) {
switch (type) { return switch (type) {
case JSON: case JSON -> "application/json; charset=utf-8";
return "application/json; charset=utf-8"; case PLAINTEXT -> "text/plain; charset=utf-8";
case PLAINTEXT: case PLAINTEXT_YAML -> "text/yaml";
return "text/plain; charset=utf-8"; case URLENCODED -> "application/x-www-form-urlencoded; charset=utf-8";
case URLENCODED: default -> throw new IllegalArgumentException("Unexpected value: " + type);
return "application/x-www-form-urlencoded; charset=utf-8"; };
default:
throw new IllegalArgumentException("Unexpected value: " + type);
}
} }
/** /**
@ -80,48 +78,48 @@ abstract class HttpAPIClient {
* @throws IOException When the I/O-operation failed. * @throws IOException When the I/O-operation failed.
*/ */
final String exec(String payload, ContentType type) throws IOException { final String exec(String payload, ContentType type) throws IOException {
BufferedReader rd = null; BufferedReader bufferedReader = null;
OutputStreamWriter wr = null; OutputStreamWriter streamWriter = null;
try { try {
HttpsURLConnection conn = (HttpsURLConnection) new URL(this.url).openConnection(); HttpsURLConnection connection = (HttpsURLConnection) new URL(this.url).openConnection();
conn.setRequestMethod("POST"); connection.setRequestMethod("POST");
conn.setDoOutput(true); connection.setDoOutput(true);
// we can receive anything! // we can receive anything!
conn.addRequestProperty("Accept", "*/*"); connection.addRequestProperty("Accept", "*/*");
// set a dummy User-Agent // set a dummy User-Agent
conn.addRequestProperty("User-Agent", "placeholder"); connection.addRequestProperty("User-Agent", "multiverse/dumps");
// this isn't required, but is technically correct // this isn't required, but is technically correct
conn.addRequestProperty("Content-Type", getContentHeader(type)); connection.addRequestProperty("Content-Type", getContentHeader(type));
// only some API requests require an access token // only some API requests require an access token
if (this.accessToken != null) { if (this.accessToken != null) {
conn.addRequestProperty("Authorization", this.accessToken); connection.addRequestProperty("Authorization", this.accessToken);
} }
wr = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8.newEncoder()); streamWriter = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8.newEncoder());
wr.write(payload); streamWriter.write(payload);
wr.flush(); streamWriter.flush();
String line; String line;
StringBuilder responseString = new StringBuilder(); StringBuilder responseString = new StringBuilder();
// this has to be initialized AFTER the data has been flushed! // this has to be initialized AFTER the data has been flushed!
rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
while ((line = rd.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
responseString.append(line); responseString.append(line);
} }
return responseString.toString(); return responseString.toString();
} finally { } finally {
if (wr != null) { if (streamWriter != null) {
try { try {
wr.close(); streamWriter.close();
} catch (IOException ignore) { } } catch (IOException ignore) { }
} }
if (rd != null) { if (bufferedReader != null) {
try { try {
rd.close(); bufferedReader.close();
} catch (IOException ignore) { } } catch (IOException ignore) { }
} }
} }

View File

@ -16,7 +16,7 @@ public class PasteServiceFactory {
return switch (type) { return switch (type) {
case PASTEGG -> new PasteGGPasteService(isPrivate); case PASTEGG -> new PasteGGPasteService(isPrivate);
case PASTEBIN -> new PastebinPasteService(isPrivate); case PASTEBIN -> new PastebinPasteService(isPrivate);
case HASTEBIN -> new HastebinPasteService(); case PASTESDEV -> new PastesDevPasteService();
case GITHUB -> new GitHubPasteService(isPrivate); case GITHUB -> new GitHubPasteService(isPrivate);
case MCLOGS -> new McloGsPasteService(); case MCLOGS -> new McloGsPasteService();
}; };

View File

@ -16,9 +16,9 @@ public enum PasteServiceType {
*/ */
PASTEBIN, PASTEBIN,
/** /**
* @see HastebinPasteService * @see PastesDevPasteService
*/ */
HASTEBIN, PASTESDEV,
/** /**
* @see GitHubPasteService * @see GitHubPasteService
*/ */

View File

@ -10,11 +10,11 @@ import net.minidev.json.parser.ParseException;
/** /**
* Pastes to {@code hastebin.com}. * Pastes to {@code hastebin.com}.
*/ */
class HastebinPasteService extends PasteService { class PastesDevPasteService extends PasteService {
private static final String HASTEBIN_POST_REQUEST = "https://hastebin.com/documents"; private static final String PASTESDEV_POST_REQUEST = "https://api.pastes.dev/post";
HastebinPasteService() { PastesDevPasteService() {
super(HASTEBIN_POST_REQUEST); super(PASTESDEV_POST_REQUEST);
} }
/** /**
@ -39,8 +39,8 @@ class HastebinPasteService extends PasteService {
@Override @Override
public String postData(String data) throws PasteFailedException { public String postData(String data) throws PasteFailedException {
try { try {
String stringJSON = this.exec(encodeData(data), ContentType.PLAINTEXT); String stringJSON = this.exec(encodeData(data), ContentType.PLAINTEXT_YAML);
return "https://hastebin.com/" + ((JSONObject) new JSONParser().parse(stringJSON)).get("key"); return "https://pastes.dev/" + ((JSONObject) new JSONParser().parse(stringJSON)).get("key");
} catch (IOException | ParseException e) { } catch (IOException | ParseException e) {
throw new PasteFailedException(e); throw new PasteFailedException(e);
} }
@ -50,13 +50,8 @@ class HastebinPasteService extends PasteService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public String postData(Map<String, String> data) throws PasteFailedException { public String postData(Map<String, String> data) throws UnsupportedOperationException {
try { throw new UnsupportedOperationException();
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);
}
} }
/** /**