From 320d1ae9d83eba6dfba969b1a264ebfdb4d9377e Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Sat, 16 Apr 2022 21:09:36 +0430 Subject: [PATCH] add support for alternative web interfaces (#342) * add support for alternative web interfaces * fix naming * won't bundle sorayomi zip * clean diff --- buildSrc/src/main/kotlin/Constants.kt | 1 + server/build.gradle.kts | 3 + .../suwayomi/tachidesk/server/JavalinSetup.kt | 6 +- .../suwayomi/tachidesk/server/ServerConfig.kt | 1 + ...WebUIManager.kt => WebInterfaceManager.kt} | 79 +++++++++++++++++++ .../src/main/resources/server-reference.conf | 1 + 6 files changed, 88 insertions(+), 3 deletions(-) rename server/src/main/kotlin/suwayomi/tachidesk/server/util/{WebUIManager.kt => WebInterfaceManager.kt} (59%) diff --git a/buildSrc/src/main/kotlin/Constants.kt b/buildSrc/src/main/kotlin/Constants.kt index 895e03f4..f8b6990f 100644 --- a/buildSrc/src/main/kotlin/Constants.kt +++ b/buildSrc/src/main/kotlin/Constants.kt @@ -15,6 +15,7 @@ const val MainClass = "suwayomi.tachidesk.MainKt" val tachideskVersion = System.getenv("ProductVersion") ?: "v0.6.3" val webUIRevisionTag = System.getenv("WebUIRevision") ?: "r942" +val sorayomiRevisionTag = System.getenv("SorayomiRevision") ?: "0.1.5" // counts commits on the master branch val tachideskRevision = runCatching { diff --git a/server/build.gradle.kts b/server/build.gradle.kts index e82af58a..d54bdb81 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -107,6 +107,9 @@ buildConfig { buildConfigField("String", "WEBUI_REPO", quoteWrap("https://github.com/Suwayomi/Tachidesk-WebUI-preview")) buildConfigField("String", "WEBUI_TAG", quoteWrap(webUIRevisionTag)) + buildConfigField("String", "SORAYOMI_REPO", quoteWrap("https://github.com/Suwayomi/Tachidesk-Sorayomi")) + buildConfigField("String", "SORAYOMI_TAG", quoteWrap(sorayomiRevisionTag)) + buildConfigField("String", "GITHUB", quoteWrap("https://github.com/Suwayomi/Tachidesk-Server")) buildConfigField("String", "DISCORD", quoteWrap("https://discord.gg/DDZdqZWaHA")) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt index d4602c26..4d943345 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt @@ -26,7 +26,7 @@ import org.kodein.di.instance import suwayomi.tachidesk.global.GlobalAPI import suwayomi.tachidesk.manga.MangaAPI import suwayomi.tachidesk.server.util.Browser -import suwayomi.tachidesk.server.util.setupWebUI +import suwayomi.tachidesk.server.util.setupWebInterface import java.io.IOException import java.util.concurrent.CompletableFuture import kotlin.concurrent.thread @@ -45,9 +45,9 @@ object JavalinSetup { fun javalinSetup() { val app = Javalin.create { config -> if (serverConfig.webUIEnabled) { - setupWebUI() + setupWebInterface() - logger.info { "Serving webUI static files" } + logger.info { "Serving web static files for ${serverConfig.webUIFlavor}" } config.addStaticFiles(applicationDirs.webUIRoot, Location.EXTERNAL) config.addSinglePageRoot("/", applicationDirs.webUIRoot + "/index.html", Location.EXTERNAL) config.registerPlugin(OpenApiPlugin(getOpenApiOptions())) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt index cc38ddcd..51e083fa 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt @@ -30,6 +30,7 @@ class ServerConfig(config: Config, moduleName: String = MODULE_NAME) : SystemPro // webUI val webUIEnabled: Boolean by overridableConfig + val webUIFlavor: String by overridableConfig val initialOpenInBrowserEnabled: Boolean by overridableConfig val webUIInterface: String by overridableConfig val electronPath: String by overridableConfig diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebUIManager.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt similarity index 59% rename from server/src/main/kotlin/suwayomi/tachidesk/server/util/WebUIManager.kt rename to server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt index 025ac8e0..d36846f8 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebUIManager.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt @@ -7,6 +7,9 @@ package suwayomi.tachidesk.server.util * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import mu.KotlinLogging import net.lingala.zip4j.ZipFile import org.kodein.di.DI @@ -14,6 +17,8 @@ import org.kodein.di.conf.global import org.kodein.di.instance import suwayomi.tachidesk.server.ApplicationDirs import suwayomi.tachidesk.server.BuildConfig +import suwayomi.tachidesk.server.serverConfig +import uy.kohesive.injekt.injectLazy import java.io.File import java.io.InputStream import java.net.HttpURLConnection @@ -23,6 +28,7 @@ import java.security.MessageDigest private val logger = KotlinLogging.logger {} private val applicationDirs by DI.global.instance() +private val json: Json by injectLazy() private val tmpDir = System.getProperty("java.io.tmpdir") private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) } @@ -44,6 +50,19 @@ private fun directoryMD5(fileDir: String): String { return digest.toHex() } +/** Make sure a valid web interface installation is available */ +fun setupWebInterface() { + when (serverConfig.webUIFlavor) { + "WebUI" -> setupWebUI() + "Sorayomi" -> setupSorayomi() + "Custom" -> { + /* do nothing */ + } + else -> setupWebUI() + } +} + +/** Make sure a valid copy of WebUI is available */ fun setupWebUI() { // check if we have webUI installed and is correct version val webUIRevisionFile = File(applicationDirs.webUIRoot + "/revision") @@ -117,3 +136,63 @@ fun setupWebUI() { logger.info { "Extracting WebUI zip Done." } } } + +/** Make sure a valid copy of Sorayomi is available */ +fun setupSorayomi() { + // check if we have Sorayomi installed and is correct version + val sorayomiVersionFile = File(applicationDirs.webUIRoot + "/version.json") + if (sorayomiVersionFile.exists() && json.parseToJsonElement( + sorayomiVersionFile.readText() + ).jsonObject["version"]!!.jsonPrimitive.content == BuildConfig.SORAYOMI_TAG + ) { + logger.info { "Sorayomi Static files exists and is the correct revision" } + logger.info { "Verifying Sorayomi Static files..." } + logger.info { "md5: " + directoryMD5(applicationDirs.webUIRoot) } + } else { + File(applicationDirs.webUIRoot).deleteRecursively() + + val sorayomiZip = "tachidesk-sorayomi-${BuildConfig.SORAYOMI_TAG}-web.zip" + val sorayomiZipPath = "$tmpDir/$sorayomiZip" + val sorayomiZipFile = File(sorayomiZipPath) + + // download sorayomi zip + val sorayomiZipURL = "${BuildConfig.SORAYOMI_REPO}/releases/download/${BuildConfig.SORAYOMI_TAG}/$sorayomiZip" + sorayomiZipFile.delete() + + logger.info { "Downloading Sorayomi zip from the Internet..." } + val data = ByteArray(1024) + + sorayomiZipFile.outputStream().use { sorayomiZipFileOut -> + + val connection = URL(sorayomiZipURL).openConnection() as HttpURLConnection + connection.connect() + val contentLength = connection.contentLength + + connection.inputStream.buffered().use { inp -> + var totalCount = 0 + + print("Download progress: % 00") + while (true) { + val count = inp.read(data, 0, 1024) + + if (count == -1) + break + + totalCount += count + val percentage = (totalCount.toFloat() / contentLength * 100).toInt().toString().padStart(2, '0') + print("\b\b$percentage") + + sorayomiZipFileOut.write(data, 0, count) + } + println() + logger.info { "Downloading Sorayomi Done." } + } + } + + // extract Sorayomi zip + logger.info { "Extracting Sorayomi zip..." } + File(applicationDirs.webUIRoot).mkdirs() + ZipFile(sorayomiZipPath).extractAll(applicationDirs.webUIRoot) + logger.info { "Extracting Sorayomi zip Done." } + } +} diff --git a/server/src/main/resources/server-reference.conf b/server/src/main/resources/server-reference.conf index eff73f80..0ed3336b 100644 --- a/server/src/main/resources/server-reference.conf +++ b/server/src/main/resources/server-reference.conf @@ -9,6 +9,7 @@ server.socksProxyPort = "" # webUI server.webUIEnabled = true +server.webUIFlavor = "WebUI" # "WebUI" or "Sorayomi" or "Custom" server.initialOpenInBrowserEnabled = true server.webUIInterface = "browser" # "browser" or "electron" server.electronPath = ""