mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-10-31 08:32:18 +01:00
Pastes, manifest reading
This commit is contained in:
parent
b63be457fd
commit
68fa07eb15
@ -121,11 +121,6 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<BukkitConfig, BukkitConne
|
||||
return playerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return bootstrap.getPlugin().getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginManager pluginManager() {
|
||||
return pluginManager;
|
||||
|
@ -103,11 +103,6 @@ public class BungeeDiscordSRV extends ProxyDiscordSRV<MainConfig, ConnectionConf
|
||||
return playerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return bootstrap.getPlugin().getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginManager pluginManager() {
|
||||
return pluginManager;
|
||||
|
@ -67,10 +67,16 @@ import com.discordsrv.common.placeholder.context.GlobalTextHandlingContext;
|
||||
import com.discordsrv.common.profile.ProfileManager;
|
||||
import com.discordsrv.common.storage.Storage;
|
||||
import com.discordsrv.common.storage.StorageType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import okhttp3.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -79,6 +85,9 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* DiscordSRV's implementation's common code.
|
||||
@ -108,6 +117,25 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
private boolean hikariLoaded = false;
|
||||
private LinkProvider linkProvider;
|
||||
|
||||
// Version
|
||||
private String version;
|
||||
private String gitRevision;
|
||||
private String gitBranch;
|
||||
|
||||
private final OkHttpClient httpClient = new OkHttpClient.Builder()
|
||||
.addInterceptor(chain -> {
|
||||
Request original = chain.request();
|
||||
return chain.proceed(
|
||||
original.newBuilder()
|
||||
.removeHeader("User-Agent")
|
||||
.addHeader("User-Agent", "DiscordSRV/" + version())
|
||||
.build()
|
||||
);
|
||||
})
|
||||
.callTimeout(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
// Internal
|
||||
private final ReentrantLock lifecycleLock = new ReentrantLock();
|
||||
|
||||
@ -129,6 +157,38 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
this.discordConnectionDetails = new DiscordConnectionDetailsImpl(this);
|
||||
this.discordConnectionManager = new JDAConnectionManager(this);
|
||||
this.channelConfig = new ChannelConfigHelper(this);
|
||||
readManifest();
|
||||
}
|
||||
|
||||
protected URL getManifest() {
|
||||
return getClass().getClassLoader().getResource(JarFile.MANIFEST_NAME);
|
||||
}
|
||||
|
||||
private void readManifest() {
|
||||
try {
|
||||
URL url = getManifest();
|
||||
if (url == null) {
|
||||
logger().error("Could not find manifest");
|
||||
return;
|
||||
}
|
||||
try (InputStream inputStream = url.openStream()) {
|
||||
Manifest manifest = new Manifest(inputStream);
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
|
||||
version = readAttribute(attributes, "Implementation-Version");
|
||||
if (version == null) {
|
||||
logger().error("Failed to get version from manifest");
|
||||
}
|
||||
gitRevision = readAttribute(attributes, "Git-Commit");
|
||||
gitBranch = readAttribute(attributes, "Git-Branch");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger().error("Failed to read manifest", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String readAttribute(Attributes attributes, String key) {
|
||||
return attributes.getValue(key);
|
||||
}
|
||||
|
||||
// DiscordSRVApi
|
||||
@ -191,6 +251,21 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
return linkProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String gitRevision() {
|
||||
return gitRevision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String gitBranch() {
|
||||
return gitBranch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelConfigHelper channelConfig() {
|
||||
return channelConfig;
|
||||
@ -278,6 +353,16 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OkHttpClient httpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapper json() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
|
||||
protected CompletableFuture<Void> invokeLifecycle(CheckedRunnable runnable, String message, boolean enable) {
|
||||
|
@ -41,8 +41,10 @@ import com.discordsrv.common.plugin.PluginManager;
|
||||
import com.discordsrv.common.profile.ProfileManager;
|
||||
import com.discordsrv.common.scheduler.Scheduler;
|
||||
import com.discordsrv.common.storage.Storage;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import dev.vankka.dependencydownload.classpath.ClasspathAppender;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -59,7 +61,6 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
Path dataDirectory();
|
||||
Scheduler scheduler();
|
||||
Console console();
|
||||
String version();
|
||||
PluginManager pluginManager();
|
||||
OnlineMode onlineMode();
|
||||
ClasspathAppender classpathAppender();
|
||||
@ -92,6 +93,14 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
// Link Provider
|
||||
LinkProvider linkProvider();
|
||||
|
||||
// Version
|
||||
@NotNull
|
||||
String version();
|
||||
@Nullable
|
||||
String gitRevision();
|
||||
@Nullable
|
||||
String gitBranch();
|
||||
|
||||
// Config
|
||||
ConnectionConfigManager<? extends ConnectionConfig> connectionConfigManager();
|
||||
ConnectionConfig connectionConfig();
|
||||
@ -124,6 +133,8 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
return (Caffeine<K, V>) Caffeine.newBuilder()
|
||||
.executor(scheduler().forkJoinPool());
|
||||
}
|
||||
OkHttpClient httpClient();
|
||||
ObjectMapper json();
|
||||
|
||||
// Lifecycle
|
||||
CompletableFuture<Void> invokeEnable();
|
||||
|
48
common/src/main/java/com/discordsrv/common/paste/Paste.java
Normal file
48
common/src/main/java/com/discordsrv/common/paste/Paste.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.paste;
|
||||
|
||||
public class Paste {
|
||||
|
||||
private final String id;
|
||||
private final String url;
|
||||
private final byte[] decryptionKey;
|
||||
|
||||
public Paste(String id, String url, byte[] decryptionKey) {
|
||||
this.id = id;
|
||||
this.url = url;
|
||||
this.decryptionKey = decryptionKey;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String url() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public byte[] decryptionKey() {
|
||||
return decryptionKey;
|
||||
}
|
||||
|
||||
public Paste withDecryptionKey(byte[] decryptionKey) {
|
||||
return new Paste(id, url, decryptionKey);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.paste;
|
||||
|
||||
public interface PasteService {
|
||||
|
||||
Paste uploadFile(byte[] fileContent) throws Throwable;
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.paste.service;
|
||||
|
||||
import com.discordsrv.common.paste.Paste;
|
||||
import com.discordsrv.common.paste.PasteService;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
public class AESEncryptedPasteService implements PasteService {
|
||||
|
||||
private final PasteService service;
|
||||
private final int keySize;
|
||||
private final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
public AESEncryptedPasteService(PasteService service, int keySize) {
|
||||
this.service = service;
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paste uploadFile(byte[] fileContent) throws Throwable {
|
||||
byte[] iv = new byte[16];
|
||||
RANDOM.nextBytes(iv);
|
||||
|
||||
SecretKey secretKey = generateKey();
|
||||
byte[] encrypted = encrypt(secretKey, fileContent, iv);
|
||||
|
||||
Paste paste = service.uploadFile(Base64.getEncoder().encode(ArrayUtils.addAll(iv, encrypted)));
|
||||
return paste.withDecryptionKey(secretKey.getEncoded());
|
||||
}
|
||||
|
||||
private SecretKey generateKey() throws NoSuchAlgorithmException {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(keySize);
|
||||
|
||||
return keyGenerator.generateKey();
|
||||
}
|
||||
|
||||
private byte[] encrypt(SecretKey key, byte[] content, byte[] iv) throws GeneralSecurityException {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
|
||||
return cipher.doFinal(content);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.paste.service;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.paste.Paste;
|
||||
import com.discordsrv.common.paste.PasteService;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import okhttp3.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
public class BinPasteService implements PasteService {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final String binUrl;
|
||||
|
||||
public BinPasteService(DiscordSRV discordSRV, String binUrl) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.binUrl = binUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paste uploadFile(byte[] fileContent) throws IOException {
|
||||
ObjectNode json = discordSRV.json().createObjectNode();
|
||||
ArrayNode files = json.putArray("files");
|
||||
ObjectNode file = files.addObject();
|
||||
|
||||
// "File name must be divisible by 16" not that I care about the file name...
|
||||
file.put("name", new String(Base64.getEncoder().encode(new byte[16])));
|
||||
file.put("content", new String(fileContent, StandardCharsets.UTF_8));
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(binUrl + "/v1/post")
|
||||
.post(RequestBody.create(MediaType.get("application/json"), json.toString()))
|
||||
.build();
|
||||
|
||||
try (Response response = discordSRV.httpClient().newCall(request).execute()) {
|
||||
ResponseBody responseBody = response.body();
|
||||
if (responseBody == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonNode responseNode = discordSRV.json().readTree(responseBody.string());
|
||||
String binId = responseNode.get("bin").asText();
|
||||
return new Paste(binId, binUrl + "/v1/" + binId + ".json", null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.paste.service;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.paste.Paste;
|
||||
import com.discordsrv.common.paste.PasteService;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import okhttp3.*;
|
||||
|
||||
public class BytebinPasteService implements PasteService {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final String bytebinUrl;
|
||||
|
||||
public BytebinPasteService(DiscordSRV discordSRV, String bytebinUrl) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.bytebinUrl = bytebinUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paste uploadFile(byte[] fileContent) throws Throwable {
|
||||
Request request = new Request.Builder()
|
||||
.url(bytebinUrl + "/post")
|
||||
.header("Content-Encoding", "gzip")
|
||||
.post(RequestBody.create(MediaType.get("application/octet-stream"), fileContent))
|
||||
.build();
|
||||
|
||||
try (Response response = discordSRV.httpClient().newCall(request).execute()) {
|
||||
ResponseBody responseBody = response.body();
|
||||
if (responseBody == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonNode responseNode = discordSRV.json().readTree(responseBody.string());
|
||||
String key = responseNode.get("key").asText();
|
||||
return new Paste(key, bytebinUrl + "/" + key, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -85,7 +85,7 @@ public class MockDiscordSRV extends AbstractDiscordSRV<MainConfig, ConnectionCon
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
public @NotNull String version() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class MockDiscordSRV extends AbstractDiscordSRV<MainConfig, ConnectionCon
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
public @NotNull String version() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -112,11 +112,6 @@ public class SpongeDiscordSRV extends ServerDiscordSRV<MainConfig, ConnectionCon
|
||||
return playerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return pluginContainer.metadata().version().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginManager pluginManager() {
|
||||
return pluginManager;
|
||||
|
@ -37,7 +37,10 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import dev.vankka.dependencydownload.classpath.ClasspathAppender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class VelocityDiscordSRV extends ProxyDiscordSRV<MainConfig, ConnectionConfig> {
|
||||
|
||||
@ -71,6 +74,16 @@ public class VelocityDiscordSRV extends ProxyDiscordSRV<MainConfig, ConnectionCo
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL getManifest() {
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
return ((URLClassLoader) classLoader).findResource(JarFile.MANIFEST_NAME);
|
||||
} else {
|
||||
throw new IllegalStateException("Class not loaded by a URLClassLoader, unable to get manifest");
|
||||
}
|
||||
}
|
||||
|
||||
public Object plugin() {
|
||||
return plugin;
|
||||
}
|
||||
@ -108,11 +121,6 @@ public class VelocityDiscordSRV extends ProxyDiscordSRV<MainConfig, ConnectionCo
|
||||
return playerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return container().getDescription().getVersion().orElseThrow(() -> new IllegalStateException("No version"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginManager pluginManager() {
|
||||
return pluginManager;
|
||||
|
Loading…
Reference in New Issue
Block a user