diff options
author | Lorenz <lo.scherf@gmail.com> | 2022-08-17 03:05:34 +0200 |
---|---|---|
committer | Lorenz <lo.scherf@gmail.com> | 2022-08-17 03:05:34 +0200 |
commit | ef58a94bf31868c4b53218474f0be04c1cd93d97 (patch) | |
tree | cb56d5969f8bebf586298475a61c521229663fda /src/main/java/at/hannibal2/skyhanni/data/repo | |
parent | 5669dbf6f68e7cacb2df6a4e37d703df8635353e (diff) | |
download | skyhanni-ef58a94bf31868c4b53218474f0be04c1cd93d97.tar.gz skyhanni-ef58a94bf31868c4b53218474f0be04c1cd93d97.tar.bz2 skyhanni-ef58a94bf31868c4b53218474f0be04c1cd93d97.zip |
moving packets around
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data/repo')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt | 172 | ||||
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt | 102 |
2 files changed, 274 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt new file mode 100644 index 000000000..8351991ab --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -0,0 +1,172 @@ +package at.hannibal2.skyhanni.data.repo + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.JsonObject +import net.minecraft.client.Minecraft +import org.apache.commons.io.FileUtils +import java.io.* +import java.net.URL +import java.nio.charset.StandardCharsets +import java.util.concurrent.CompletableFuture +import java.util.concurrent.atomic.AtomicBoolean + +class RepoManager(private val configLocation: File) { + val gson: Gson = GsonBuilder().setPrettyPrinting().create() + private var latestRepoCommit: String? = null + private val repoLocation: File = File(configLocation, "repo") + + fun loadRepoInformation() { + atomicShouldManuallyReload.set(true) + if (SkyHanniMod.feature.apiData.repoAutoUpdate) { + fetchRepository().thenRun(this::reloadRepository) + } else { + reloadRepository() + } + } + + private val atomicShouldManuallyReload = AtomicBoolean(false)//TODO FIX + + fun updateRepo() { + atomicShouldManuallyReload.set(true) + fetchRepository(true).thenRun { this.reloadRepository("Repo updated successful :)") } + } + + fun reloadLocalRepo() { + atomicShouldManuallyReload.set(true) + reloadRepository("Repo loaded from local files successful :)") + } + + private fun fetchRepository(command: Boolean = false): CompletableFuture<Boolean> { + return CompletableFuture.supplyAsync { + try { + val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) + latestRepoCommit = null + try { + InputStreamReader(URL(getCommitApiUrl()).openStream()) + .use { inReader -> + val commits: JsonObject = gson.fromJson(inReader, JsonObject::class.java) + latestRepoCommit = commits["sha"].asString + } + } catch (e: Exception) { + e.printStackTrace() + } + if (latestRepoCommit == null || latestRepoCommit!!.isEmpty()) return@supplyAsync false + if (File(configLocation, "repo").exists()) { + if (currentCommitJSON != null && currentCommitJSON["sha"].asString == latestRepoCommit) { + if (command) { + LorenzUtils.chat("§e[SkyHanni] §7The repo is already up to date!") + atomicShouldManuallyReload.set(false) + } + return@supplyAsync false + } + } + RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() + val itemsZip = File(repoLocation, "sh-repo-main.zip") + try { + itemsZip.createNewFile() + } catch (e: IOException) { + return@supplyAsync false + } + val url = URL(getDownloadUrl(latestRepoCommit)) + val urlConnection = url.openConnection() + urlConnection.connectTimeout = 15000 + urlConnection.readTimeout = 30000 + try { + urlConnection.getInputStream().use { `is` -> + FileUtils.copyInputStreamToFile( + `is`, + itemsZip + ) + } + } catch (e: IOException) { + e.printStackTrace() + System.err.println("Failed to download SkyHanni Repo! Please report this issue to the mod creator") + if (command) { + LorenzUtils.error("An error occurred while trying to reload the repo! See logs for more info.") + } + return@supplyAsync false + } + RepoUtils.unzipIgnoreFirstFolder( + itemsZip.absolutePath, + repoLocation.absolutePath + ) + if (currentCommitJSON == null || currentCommitJSON["sha"].asString != latestRepoCommit) { + val newCurrentCommitJSON = JsonObject() + newCurrentCommitJSON.addProperty("sha", latestRepoCommit) + try { + writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) + } catch (ignored: IOException) { + } + } + } catch (e: Exception) { + e.printStackTrace() + } + true + } + } + + private fun reloadRepository(answerMessage: String = ""): CompletableFuture<Void?> { + val comp = CompletableFuture<Void?>() + if (!atomicShouldManuallyReload.get()) return comp + Minecraft.getMinecraft().addScheduledTask { + try { + RepositoryReloadEvent(repoLocation, gson).postAndCatch() + comp.complete(null) + if (answerMessage.isNotEmpty()) { + LorenzUtils.chat("§e[SkyHanni] §a$answerMessage") + } + } catch (e: java.lang.Exception) { + comp.completeExceptionally(e) + LorenzUtils.error("An error occurred while trying to reload the repo! See logs for more info.") + } + } + return comp + } + + /** + * Parses a file in to a JsonObject. + */ + private fun getJsonFromFile(file: File?): JsonObject? { + try { + BufferedReader( + InputStreamReader( + FileInputStream(file), + StandardCharsets.UTF_8 + ) + ).use { reader -> + return gson.fromJson(reader, JsonObject::class.java) + } + } catch (e: java.lang.Exception) { + return null + } + } + + private fun getCommitApiUrl(): String { + val repoUser = "hannibal00212" + val repoName = "SkyHanni-REPO" + val repoBranch = "main" + return String.format("https://api.github.com/repos/%s/%s/commits/%s", repoUser, repoName, repoBranch) + } + + private fun getDownloadUrl(commitId: String?): String { + val repoUser = "hannibal00212" + val repoName = "SkyHanni-REPO" + return String.format("https://github.com/%s/%s/archive/%s.zip", repoUser, repoName, commitId) + } + + @Throws(IOException::class) + fun writeJson(json: JsonObject?, file: File) { + file.createNewFile() + BufferedWriter( + OutputStreamWriter( + FileOutputStream(file), + StandardCharsets.UTF_8 + ) + ).use { writer -> writer.write(gson.toJson(json)) } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt new file mode 100644 index 000000000..969b526cc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt @@ -0,0 +1,102 @@ +package at.hannibal2.skyhanni.data.repo + +import com.google.gson.Gson +import com.google.gson.JsonObject +import java.io.* +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.util.zip.ZipInputStream + +object RepoUtils { + + fun recursiveDelete(file: File) { + if (file.isDirectory && !Files.isSymbolicLink(file.toPath())) { + for (child in file.listFiles()) { + recursiveDelete(child) + } + } + file.delete() + } + + /** + * Modified from https://www.journaldev.com/960/java-unzip-file-example + */ + fun unzipIgnoreFirstFolder(zipFilePath: String, destDir: String) { + val dir = File(destDir) + // create output directory if it doesn't exist + if (!dir.exists()) dir.mkdirs() + val fis: FileInputStream + //buffer for read and write data to file + val buffer = ByteArray(1024) + try { + fis = FileInputStream(zipFilePath) + val zis = ZipInputStream(fis) + var ze = zis.nextEntry + while (ze != null) { + if (!ze.isDirectory) { + var fileName = ze.name + fileName = fileName.substring(fileName.split("/").toTypedArray()[0].length + 1) + val newFile = File(destDir + File.separator + fileName) + //create directories for sub directories in zip + File(newFile.parent).mkdirs() + if (!isInTree(dir, newFile)) { + throw RuntimeException( + "SkyHanni detected an invalid zip file. This is a potential security risk, please report this on the SkyHanni discord." + ) + } + val fos = FileOutputStream(newFile) + var len: Int + while (zis.read(buffer).also { len = it } > 0) { + fos.write(buffer, 0, len) + } + fos.close() + } + //close this ZipEntry + zis.closeEntry() + ze = zis.nextEntry + } + //close last ZipEntry + zis.closeEntry() + zis.close() + fis.close() + } catch (e: IOException) { + e.printStackTrace() + } + } + + @Throws(IOException::class) + private fun isInTree(rootDirectory: File, file: File): Boolean { + var rootDirectory = rootDirectory + var file: File? = file + file = file!!.canonicalFile + rootDirectory = rootDirectory.canonicalFile + while (file != null) { + if (file == rootDirectory) return true + file = file.parentFile + } + return false + } + + fun getConstant(repoLocation: File, constant: String, gson: Gson): JsonObject? { + return getConstant(repoLocation, constant, gson, JsonObject::class.java) + } + + private fun <T> getConstant(repo: File, constant: String, gson: Gson, clazz: Class<T>?): T? { + if (repo.exists()) { + val jsonFile = File(repo, "constants/$constant.json") + try { + BufferedReader( + InputStreamReader( + FileInputStream(jsonFile), + StandardCharsets.UTF_8 + ) + ).use { reader -> + return gson.fromJson(reader, clazz) + } + } catch (e: Exception) { + return null + } + } + return null + } +}
\ No newline at end of file |