mirror of
https://github.com/Anvilcraft/modpacktools
synced 2024-05-19 03:44:06 +02:00
184 lines
5.3 KiB
Kotlin
184 lines
5.3 KiB
Kotlin
@file:JvmName("Util")
|
|
|
|
package ley.anvil.modpacktools.util
|
|
|
|
import com.google.gson.JsonObject
|
|
import com.google.gson.JsonParser
|
|
import ley.anvil.modpacktools.HTTP_CLIENT
|
|
import net.sourceforge.argparse4j.inf.Argument
|
|
import net.sourceforge.argparse4j.inf.ArgumentParser
|
|
import okhttp3.MediaType
|
|
import okhttp3.MediaType.Companion.toMediaType
|
|
import okhttp3.Request
|
|
import okhttp3.RequestBody.Companion.toRequestBody
|
|
import okhttp3.Response
|
|
import org.apache.commons.io.FileUtils
|
|
import java.io.File
|
|
import java.io.FileInputStream
|
|
import java.io.IOException
|
|
import java.net.URI
|
|
import java.net.URL
|
|
import java.nio.file.FileVisitResult
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
import java.nio.file.SimpleFileVisitor
|
|
import java.nio.file.attribute.BasicFileAttributes
|
|
import java.util.zip.ZipEntry
|
|
import java.util.zip.ZipInputStream
|
|
import java.util.zip.ZipOutputStream
|
|
import kotlin.reflect.KClass
|
|
import kotlin.reflect.KFunction
|
|
import kotlin.reflect.full.functions
|
|
import kotlin.reflect.jvm.isAccessible
|
|
|
|
/**
|
|
* Reads a Json [File]
|
|
*
|
|
* @receiver the file to read from
|
|
* @return the file content as [JsonObject]
|
|
*/
|
|
fun File.readAsJson(): JsonObject {
|
|
require(this.exists()) {"File to read doesn't exist"}
|
|
|
|
return JsonParser.parseReader(reader()) as JsonObject
|
|
}
|
|
|
|
/**
|
|
* sends a HTTP POST request
|
|
*
|
|
* @receiver the [URL] to send the request to
|
|
* @param contentType what content type should be used.
|
|
* @param payload the payload to send
|
|
* @param additionalHeaders additional headers that should be added to the request
|
|
* @return the response
|
|
*/
|
|
@Throws(IOException::class)
|
|
fun URL.httpPostStr(payload: String, contentType: MediaType? = null, additionalHeaders: Map<String, String>? = null): Response =
|
|
HTTP_CLIENT.newCall(
|
|
Request.Builder()
|
|
.url(this)
|
|
.post(payload.toRequestBody(contentType))
|
|
.apply {additionalHeaders?.forEach {addHeader(it.key, it.value)}}
|
|
.build()
|
|
).execute()
|
|
|
|
/**
|
|
* sends a HTTP POST request
|
|
*
|
|
* @receiver the [URL] to send the request to
|
|
* @param contentType what content type should be used. Example: `"application/json; utf-8"`
|
|
* @param payload the payload to send
|
|
* @param additionalHeaders additional headers that should be added to the request
|
|
* @return the response
|
|
*/
|
|
@Throws(IOException::class)
|
|
fun URL.httpPostStr(payload: String, contentType: String, additionalHeaders: Map<String, String>? = null): Response {
|
|
return this.httpPostStr(
|
|
payload,
|
|
contentType.toMediaType(),
|
|
additionalHeaders
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Sanitizes a [URL] to be valid by url-encoding illegal chars like spaces
|
|
*
|
|
* @receiver the [URL] to sanitize
|
|
* @return the sanitized [URL]
|
|
*/
|
|
|
|
fun URL.sanitize(): URL? =
|
|
try {
|
|
URI(
|
|
this.protocol,
|
|
this.userInfo,
|
|
this.host,
|
|
this.port,
|
|
this.path,
|
|
this.query,
|
|
this.ref
|
|
).toURL()
|
|
} catch(e: Exception) {
|
|
null
|
|
}
|
|
|
|
/**
|
|
* gets a [KFunction] from the receiver and makes it accessible
|
|
*
|
|
* @param name the name of the [KFunction] to get
|
|
* @receiver the [KClass] to get the [KFunction] from
|
|
*/
|
|
fun KClass<*>.getFun(name: String): KFunction<*>? = this.functions.find {it.name == name}?.apply {isAccessible = true}
|
|
|
|
/**
|
|
* zips a directory.
|
|
*
|
|
* @receiver the directory to zip
|
|
* @param zStream the zip stream to write to
|
|
*/
|
|
fun Path.toZip(zStream: ZipOutputStream) {
|
|
require(this.toFile().exists()) {"File must exist"}
|
|
|
|
Files.walkFileTree(
|
|
this,
|
|
object : SimpleFileVisitor<Path>() {
|
|
override fun visitFile(file: Path, attrs: BasicFileAttributes?): FileVisitResult {
|
|
zStream.putNextEntry(ZipEntry(this@toZip.relativize(file).toString()))
|
|
Files.copy(file, zStream)
|
|
zStream.closeEntry()
|
|
return FileVisitResult.CONTINUE
|
|
}
|
|
|
|
override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes?): FileVisitResult {
|
|
val path = this@toZip.relativize(dir).toString()
|
|
zStream.putNextEntry(ZipEntry("$path/")) // slash required to add directory entry
|
|
return FileVisitResult.CONTINUE
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
/**
|
|
* zips a directory.
|
|
*
|
|
* @receiver the directory to zip
|
|
* @param zStream the zip stream to write to
|
|
*/
|
|
fun File.toZip(zStream: ZipOutputStream) = this.toPath().toZip(zStream)
|
|
|
|
/**
|
|
* Unzips a zip [File] to a given directory
|
|
*
|
|
* @receiver the zip [File] to unzip
|
|
* @param outputDir the dir to unzip to
|
|
*/
|
|
fun File.unzip(outputDir: File) {
|
|
require(this.exists()) {"File must exist"}
|
|
|
|
val stream = ZipInputStream(FileInputStream(this))
|
|
while(true) {
|
|
val entry = stream.nextEntry ?: break
|
|
val outfile = File(outputDir, entry.name)
|
|
FileUtils.copyToFile(stream, outfile)
|
|
}
|
|
stream.close()
|
|
}
|
|
|
|
/**
|
|
* this makes arguments for [ArgumentParser]s look cleaner
|
|
*
|
|
* @receiver the [ArgumentParser] to add the argument to
|
|
* @param names the names the [Argument] will have
|
|
* @param block this will be called on the [Argument].
|
|
* it is for settings like help message
|
|
*/
|
|
fun ArgumentParser.arg(vararg names: String, block: Argument.() -> Unit) {
|
|
addArgument(*names).block()
|
|
}
|
|
|
|
/**
|
|
* Gets the base name of the file without the directory.
|
|
*/
|
|
val File.baseName
|
|
get() = this.toPath().fileName.toString()
|