Skip to content

Commit

Permalink
Resource pack fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Stonley890 committed Aug 19, 2024
1 parent 3b04f3e commit fd24e88
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 49 deletions.
2 changes: 1 addition & 1 deletion dreamvisitor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.stonley890</groupId>
<artifactId>dreamvisitor</artifactId>
<version>2.13.11</version>
<version>2.13.12</version>
<packaging>jar</packaging>

<name>Dreamvisitor</name>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package io.github.stonley890.dreamvisitor.discord.commands;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.github.stonley890.dreamvisitor.Dreamvisitor;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Properties;

Expand All @@ -22,68 +29,125 @@ public class DCmdResourcepackupdate implements DiscordCommand {

@Override
public void onCommand(@NotNull SlashCommandInteractionEvent event) {
String resourcePackURL = null;

try (InputStream input = new FileInputStream("server.properties")) {
Properties prop = new Properties();
prop.load(input);
resourcePackURL = prop.getProperty("resource-pack");
} catch (Exception e) {
event.reply("Dreamvisitor was unable to read server.properties: " + e.getMessage()).queue();
event.deferReply().queue();

URL resourcePackURL;
try {
resourcePackURL = getLatestReleaseURL(Dreamvisitor.getPlugin().getConfig().getString("resourcePackRepo"));
Dreamvisitor.debug("Found URL.");
} catch (IOException e) {
event.reply("Dreamvisitor was unable to find the resource pack URL: " + e.getMessage()).queue();
return;
}

if (resourcePackURL != null) {
try {
Dreamvisitor.debug("Attempting to download the resource pack.");
HttpURLConnection connection = (HttpURLConnection) resourcePackURL.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(10000); // timeout
connection.connect();

if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
Dreamvisitor.debug("Generating hash.");
InputStream is = connection.getInputStream();
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
byte[] buffer = new byte[1024];
int bytesRead;

while ((bytesRead = is.read(buffer)) != -1) {
sha1.update(buffer, 0, bytesRead);
}

event.deferReply().queue();
byte[] hashBytes = sha1.digest();
StringBuilder hash = new StringBuilder();

try {
URL url = new URL(resourcePackURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(10000); // timeout
connection.connect();
for (byte hashByte : hashBytes) {
hash.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
}

if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = connection.getInputStream();
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
byte[] buffer = new byte[1024];
int bytesRead;
String newHash = hash.toString();
Dreamvisitor.debug("New hash: " + newHash);
Dreamvisitor.debug("Writing changes to server.properties.");

while ((bytesRead = is.read(buffer)) != -1) {
sha1.update(buffer, 0, bytesRead);
}
try {
Properties properties = getProperties(resourcePackURL, newHash);

byte[] hashBytes = sha1.digest();
StringBuilder hash = new StringBuilder();
// Save the updated properties back to the file with UTF-8 encoding
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("server.properties"), StandardCharsets.UTF_8));
properties.store(writer, null);
writer.close();

for (byte hashByte : hashBytes) {
hash.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
}
Dreamvisitor.debug("Success.");
Dreamvisitor.restartScheduled = true;
event.getHook().editOriginal("The resource pack URL has been updated to " + resourcePackURL +
". The SHA1 hash has been updated to " + newHash + ". The server must restart for changes to take effect. " +
"I will restart it automatically when 0 players are online. You can cancel this with `/schedulerestart`.").queue();

String newHash = hash.toString();
} catch (IOException e) {
event.reply("Dreamvisitor encountered an while modifying server.properties: " + e.getMessage()).queue();
}
}
} catch (Exception e) {
event.reply("Dreamvisitor encountered an error: " + e.getMessage()).queue();
}

try (InputStream input = new FileInputStream("server.properties")) {
Properties prop = new Properties();
prop.load(input);

prop.setProperty("resource-pack-sha1", newHash); // Update the hash property
Dreamvisitor.getPlugin().saveConfig();
}

try (OutputStream output = new FileOutputStream("server.properties")) {
prop.store(output, null);
event.getHook().editOriginal("Hash updated to " + newHash + "!").queue();
}
} catch (IOException e) {
event.reply("Dreamvisitor encountered an error: " + e.getMessage()).queue();
}
}
} catch (Exception e) {
event.reply("Dreamvisitor encountered an error: " + e.getMessage()).queue();
}
private static @NotNull Properties getProperties(URL resourcePackURL, String newHash) throws IOException {
// Load the server.properties file with UTF-8 encoding
Properties properties = new Properties();
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("server.properties"), StandardCharsets.UTF_8));
properties.load(reader);
reader.close();

properties.setProperty("resource-pack", String.valueOf(resourcePackURL)); // Update the resource pack property
properties.setProperty("resource-pack-sha1", newHash); // Update the hash property
return properties;
}

@NotNull
@Contract("_ -> new")
private static URL getLatestReleaseURL(String repo) throws IOException {
// Create a URL object
URL url = new URL("https://api.github.com/repos/WOFTNW/Dragonspeak/releases/latest");
Dreamvisitor.debug("Finding latest artifact at " + url);

// Open a connection to the URL
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");

// Read the response
Dreamvisitor.debug("Sending request.");
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
Dreamvisitor.debug("Parsing response.");
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}

// Close connections
in.close();
connection.disconnect();

// Parse the JSON response using Gson
Dreamvisitor.debug("Converting to JSON.");
JsonElement jsonElement = JsonParser.parseString(content.toString());
JsonObject jsonObject = jsonElement.getAsJsonObject();

// Access the assets array
Dreamvisitor.debug("Locating assets[0].browser_download_url");
JsonArray assets = jsonObject.getAsJsonArray("assets");
if (!assets.isEmpty()) {
// Get the first asset's browser_download_url
JsonObject firstAsset = assets.get(0).getAsJsonObject();

return new URL(firstAsset.get("browser_download_url").getAsString());
} else {
event.reply("Could not get URL of resource pack.").queue();
throw new FileNotFoundException();
}
Dreamvisitor.getPlugin().saveConfig();
}
}
7 changes: 6 additions & 1 deletion dreamvisitor/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,9 @@ minutesPerYear: 43200
# This is used to keep time accurately, even if the server goes offline.
# Do not change this value.
# Default: 0
lastUpdateMilli: 0
lastUpdateMilli: 0

# The repository path of the server resource pack.
# Dreamvisitor will pull the first artifact from the latest release on pack update.
# Default: "WOFTNW/Dragonspeak"
resourcePackRepo: "WOFTNW/Dragonspeak"

0 comments on commit fd24e88

Please sign in to comment.