From 99167bd4bcb2841cfba543496834ca5a65ab962e Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Tue, 4 Jul 2023 19:25:23 +0200 Subject: [PATCH] Add logic to support different webUIs --- server/build.gradle.kts | 4 - .../server/util/WebInterfaceManager.kt | 84 ++++++++++++++++--- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 4d1d6bceed..a0f6465317 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -101,11 +101,7 @@ buildConfig { buildConfigField("String", "BUILD_TYPE", quoteWrap(if (System.getenv("ProductBuildType") == "Stable") "Stable" else "Preview")) buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString()) - - buildConfigField("String", "WEBUI_REPO", quoteWrap("https://github.com/Suwayomi/Tachidesk-WebUI-preview")) buildConfigField("String", "WEBUI_TAG", quoteWrap(webUIRevisionTag)) - buildConfigField("String", "WEBUI_VERSION_MAPPING_URL", quoteWrap("https://raw.githubusercontent.com/Suwayomi/Tachidesk-WebUI/master/src/versionToServerVersionMapping.json")) - 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/util/WebInterfaceManager.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt index ba7c4f7409..5cc4bd97bf 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt @@ -13,11 +13,11 @@ import org.json.JSONArray import org.kodein.di.DI import org.kodein.di.conf.global import org.kodein.di.instance -import suwayomi.tachidesk.manga.impl.update.Updater import suwayomi.tachidesk.server.ApplicationDirs import suwayomi.tachidesk.server.BuildConfig import suwayomi.tachidesk.server.serverConfig import java.io.File +import java.io.InputStream import java.net.HttpURLConnection import java.net.URL import java.nio.charset.StandardCharsets @@ -34,7 +34,7 @@ private val tmpDir = System.getProperty("java.io.tmpdir") private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) } enum class WebUIChannel { - BUNDLED, // the version bundled with the server release + BUNDLED, // the default webUI version bundled with the server release STABLE, PREVIEW; @@ -45,12 +45,20 @@ enum class WebUIChannel { } } +enum class WebUI(var repoUrl: String, var versionMappingUrl: String, var zipFile: String) { + WEBUI( + "https://github.com/Suwayomi/Tachidesk-WebUI-preview", + "https://raw.githubusercontent.com/Suwayomi/Tachidesk-WebUI/master/src/versionToServerVersionMapping.json", + "Tachidesk-WebUI.zip" + ) +} + +const val DEFAULT_WEB_UI = "WebUI" + + object WebInterfaceManager { private val logger = KotlinLogging.logger {} private const val webUIPreviewVersion = "PREVIEW" - private const val baseReleasesUrl = "${BuildConfig.WEBUI_REPO}/releases" - private const val downloadSpecificVersionBaseUrl = "$baseReleasesUrl/download" - private const val downloadLatestVersionBaseUrl = "$baseReleasesUrl/latest/download" private const val lastWebUIUpdateCheckKey = "lastWebUIUpdateCheckKey" private val preferences = Preferences.userNodeForPackage(WebInterfaceManager::class.java) @@ -66,7 +74,8 @@ object WebInterfaceManager { } private fun scheduleWebUIUpdateCheck() { - if (!isAutoUpdateEnabled() || serverConfig.webUIFlavor == "Custom") { + val disableAutoUpdate = !isAutoUpdateEnabled() || serverConfig.webUIFlavor == "Custom" + if (disableAutoUpdate) { currentUpdateTask?.cancel() return } @@ -100,7 +109,7 @@ object WebInterfaceManager { logger.info { "WebUI Static files exists, version= $currentVersion" } if (!isLocalWebUIValid(applicationDirs.webUIRoot)) { - downloadLatestCompatibleVersion() + doInitialSetup() return } @@ -112,7 +121,52 @@ object WebInterfaceManager { } logger.info { "No WebUI Static files found, starting download..." } - downloadLatestCompatibleVersion() + doInitialSetup() + } + + + /** + * Tries to download the latest compatible version for the selected webUI and falls back to the default webUI in case of errors. + */ + private fun doInitialSetup() { + val downloadSucceeded = downloadLatestCompatibleVersion() + + val fallbackToDefaultWebUI = !downloadSucceeded + if (!fallbackToDefaultWebUI) { + return + } + + if (serverConfig.webUIFlavor != DEFAULT_WEB_UI) { + logger.info { "doInitialSetup: fallback to default webUI \"$DEFAULT_WEB_UI\"" } + + serverConfig.webUIFlavor = DEFAULT_WEB_UI + + val fallbackToBundledVersion = !downloadLatestCompatibleVersion() + if (!fallbackToBundledVersion) { + return + } + } + + logger.error { "doInitialSetup: fallback to bundled default webUI \"$DEFAULT_WEB_UI\"" } + + extractBundledWebUI() + } + + private fun extractBundledWebUI() { + val resourceWebUI: InputStream = BuildConfig::class.java.getResourceAsStream("/WebUI.zip") ?: throw Error("No bundled webUI version found") + + logger.info { "Using the bundled WebUI zip..." } + val webUIZip = WebUI.WEBUI.zipFile + val webUIZipPath = "$tmpDir/$webUIZip" + val webUIZipFile = File(webUIZipPath) + resourceWebUI.use { input -> + webUIZipFile.outputStream().use { output -> + input.copyTo(output) + } + } + + File(applicationDirs.webUIRoot).deleteRecursively() + extractDownload(webUIZipPath, applicationDirs.webUIRoot) } private fun checkForUpdate() { @@ -124,6 +178,10 @@ object WebInterfaceManager { } private fun getDownloadUrlFor(version: String): String { + val baseReleasesUrl = "${WebUI.WEBUI.repoUrl}/releases" + val downloadSpecificVersionBaseUrl = "$baseReleasesUrl/download" + val downloadLatestVersionBaseUrl = "$baseReleasesUrl/latest/download" + return if (version == webUIPreviewVersion) downloadLatestVersionBaseUrl else "$downloadSpecificVersionBaseUrl/$version" } @@ -191,7 +249,7 @@ object WebInterfaceManager { } val currentServerVersionNumber = extractVersion(BuildConfig.REVISION) - val webUIToServerVersionMappings = JSONArray(URL(BuildConfig.WEBUI_VERSION_MAPPING_URL).readText()) + val webUIToServerVersionMappings = JSONArray(URL(WebUI.WEBUI.versionMappingUrl).readText()) logger.debug { "webUIChannel= ${serverConfig.webUIChannel} currentServerVersion= ${BuildConfig.REVISION}, mappingFile= $webUIToServerVersionMappings" } @@ -215,14 +273,14 @@ object WebInterfaceManager { throw Exception("No compatible webUI version found") } - fun downloadLatestCompatibleVersion(retryCount: Int = 0) { + fun downloadLatestCompatibleVersion(retryCount: Int = 0): Boolean { val latestCompatibleVersion = try { getLatestCompatibleVersion() } catch (e: Exception) { BuildConfig.WEBUI_TAG } - val webUIZip = "Tachidesk-WebUI.zip" + val webUIZip = WebUI.WEBUI.zipFile val webUIZipPath = "$tmpDir/$webUIZip" val webUIZipFile = File(webUIZipPath) @@ -243,7 +301,7 @@ object WebInterfaceManager { return downloadLatestCompatibleVersion(retryCount + 1) } - return + return false } File(applicationDirs.webUIRoot).deleteRecursively() @@ -252,6 +310,8 @@ object WebInterfaceManager { logger.info { "Extracting WebUI zip..." } extractDownload(webUIZipPath, applicationDirs.webUIRoot) logger.info { "Extracting WebUI zip Done." } + + return true } private fun downloadVersion(url: String, zipFile: File) {