mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-06-30 17:34:39 -05:00
Improve Playwright handling (#479)
* Improve playwright * Move DriverJar.java and Chromium.kt
This commit is contained in:
@@ -10,6 +10,7 @@ dex2jar = "v56"
|
|||||||
rhino = "1.7.14"
|
rhino = "1.7.14"
|
||||||
settings = "1.0.0-RC"
|
settings = "1.0.0-RC"
|
||||||
twelvemonkeys = "3.9.4"
|
twelvemonkeys = "3.9.4"
|
||||||
|
playwright = "1.28.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# Kotlin
|
# Kotlin
|
||||||
@@ -98,7 +99,7 @@ zip4j = "net.lingala.zip4j:zip4j:2.11.2"
|
|||||||
junrar = "com.github.junrar:junrar:7.5.3"
|
junrar = "com.github.junrar:junrar:7.5.3"
|
||||||
|
|
||||||
# CloudflareInterceptor
|
# CloudflareInterceptor
|
||||||
playwright = "com.microsoft.playwright:playwright:1.28.0"
|
playwright = { module = "com.microsoft.playwright:playwright", version.ref = "playwright" }
|
||||||
|
|
||||||
# AES/CBC/PKCS7Padding Cypher provider
|
# AES/CBC/PKCS7Padding Cypher provider
|
||||||
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.72"
|
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.72"
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ main() {
|
|||||||
set -- "${POSITIONAL_ARGS[@]}"
|
set -- "${POSITIONAL_ARGS[@]}"
|
||||||
|
|
||||||
OS="$1"
|
OS="$1"
|
||||||
|
PLAYWRIGHT_VERSION="$(cat gradle/libs.versions.toml | grep -oP "playwright = \"\K([0-9\.]*)(?=\")")"
|
||||||
|
PLAYWRIGHT_REVISION="$(curl --silent "https://raw.githubusercontent.com/microsoft/playwright/v$PLAYWRIGHT_VERSION/packages/playwright-core/browsers.json" 2>&1 | grep -ozP "\"name\": \"chromium\",\n *\"revision\": \"\K[0-9]*")"
|
||||||
JAR="$(ls server/build/*.jar | tail -n1)"
|
JAR="$(ls server/build/*.jar | tail -n1)"
|
||||||
RELEASE_NAME="$(echo "${JAR%.*}" | xargs basename)-$OS"
|
RELEASE_NAME="$(echo "${JAR%.*}" | xargs basename)-$OS"
|
||||||
RELEASE_VERSION="$(tmp="${JAR%-*}"; echo "${tmp##*-}" | tr -d v)"
|
RELEASE_VERSION="$(tmp="${JAR%-*}"; echo "${tmp##*-}" | tr -d v)"
|
||||||
@@ -57,6 +59,9 @@ main() {
|
|||||||
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
||||||
download_jre_and_electron
|
download_jre_and_electron
|
||||||
|
|
||||||
|
PLAYWRIGHT_PLATFORM="linux"
|
||||||
|
setup_playwright
|
||||||
|
|
||||||
RELEASE="$RELEASE_NAME.tar.gz"
|
RELEASE="$RELEASE_NAME.tar.gz"
|
||||||
make_linux_bundle
|
make_linux_bundle
|
||||||
move_release_to_output_dir
|
move_release_to_output_dir
|
||||||
@@ -70,6 +75,9 @@ main() {
|
|||||||
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
||||||
download_jre_and_electron
|
download_jre_and_electron
|
||||||
|
|
||||||
|
PLAYWRIGHT_PLATFORM="mac"
|
||||||
|
setup_playwright
|
||||||
|
|
||||||
RELEASE="$RELEASE_NAME.zip"
|
RELEASE="$RELEASE_NAME.zip"
|
||||||
make_macos_bundle
|
make_macos_bundle
|
||||||
move_release_to_output_dir
|
move_release_to_output_dir
|
||||||
@@ -83,6 +91,9 @@ main() {
|
|||||||
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
||||||
download_jre_and_electron
|
download_jre_and_electron
|
||||||
|
|
||||||
|
PLAYWRIGHT_PLATFORM="mac-arm64"
|
||||||
|
setup_playwright
|
||||||
|
|
||||||
RELEASE="$RELEASE_NAME.zip"
|
RELEASE="$RELEASE_NAME.zip"
|
||||||
make_macos_bundle
|
make_macos_bundle
|
||||||
move_release_to_output_dir
|
move_release_to_output_dir
|
||||||
@@ -96,6 +107,9 @@ main() {
|
|||||||
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
||||||
download_jre_and_electron
|
download_jre_and_electron
|
||||||
|
|
||||||
|
PLAYWRIGHT_PLATFORM="win64"
|
||||||
|
setup_playwright
|
||||||
|
|
||||||
RELEASE="$RELEASE_NAME.zip"
|
RELEASE="$RELEASE_NAME.zip"
|
||||||
make_windows_bundle
|
make_windows_bundle
|
||||||
move_release_to_output_dir
|
move_release_to_output_dir
|
||||||
@@ -113,6 +127,9 @@ main() {
|
|||||||
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
|
||||||
download_jre_and_electron
|
download_jre_and_electron
|
||||||
|
|
||||||
|
PLAYWRIGHT_PLATFORM="win64"
|
||||||
|
setup_playwright
|
||||||
|
|
||||||
RELEASE="$RELEASE_NAME.zip"
|
RELEASE="$RELEASE_NAME.zip"
|
||||||
make_windows_bundle
|
make_windows_bundle
|
||||||
move_release_to_output_dir
|
move_release_to_output_dir
|
||||||
@@ -268,6 +285,11 @@ make_windows_package() {
|
|||||||
"$RELEASE_NAME/jre.wxs" "$RELEASE_NAME/electron.wxs" -o "$RELEASE"
|
"$RELEASE_NAME/jre.wxs" "$RELEASE_NAME/electron.wxs" -o "$RELEASE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_playwright() {
|
||||||
|
mkdir "$RELEASE_NAME/bin"
|
||||||
|
curl -L "https://playwright.azureedge.net/builds/chromium/$PLAYWRIGHT_REVISION/chromium-$PLAYWRIGHT_PLATFORM.zip" -o "$RELEASE_NAME/bin/chromium.zip"
|
||||||
|
}
|
||||||
|
|
||||||
# Error handler
|
# Error handler
|
||||||
# set -u: Treat unset variables as an error when substituting.
|
# set -u: Treat unset variables as an error when substituting.
|
||||||
# set -o pipefail: Prevents errors in pipeline from being masked.
|
# set -o pipefail: Prevents errors in pipeline from being masked.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.network.interceptor;
|
package suwayomi.tachidesk.server.util;
|
||||||
|
|
||||||
import com.microsoft.playwright.impl.driver.Driver;
|
import com.microsoft.playwright.impl.driver.Driver;
|
||||||
|
|
||||||
@@ -26,22 +26,9 @@ import java.util.Collections;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
exact copy of https://github.com/microsoft/playwright-java/blob/4d278c391e3c50738ddea6c3e324a4bbbf719d86/driver-bundle/src/main/java/com/microsoft/playwright/impl/driver/jar/DriverJar.java
|
* Copy of <a href="https://github.com/microsoft/playwright-java/blob/8c0231b0f739656e8a86bc58fca9ee778ddc571b/driver-bundle/src/main/java/com/microsoft/playwright/impl/driver/jar/DriverJar.java">DriverJar</a>
|
||||||
with diff:
|
* with support for pre-installing chromium and only supports chromium playwright
|
||||||
108a109,116
|
|
||||||
>
|
|
||||||
> private FileSystem initFileSystem(URI uri) throws IOException {
|
|
||||||
> try {
|
|
||||||
> return FileSystems.newFileSystem(uri, Collections.emptyMap());
|
|
||||||
> } catch (FileSystemAlreadyExistsException e) {
|
|
||||||
> return null;
|
|
||||||
> }
|
|
||||||
> }
|
|
||||||
116c124
|
|
||||||
< try (FileSystem fileSystem = "jar".equals(uri.getScheme()) ? FileSystems.newFileSystem(uri, Collections.emptyMap()) : null) {
|
|
||||||
---
|
|
||||||
> try (FileSystem fileSystem = "jar".equals(uri.getScheme()) ? initFileSystem(uri) : null) {
|
|
||||||
*/
|
*/
|
||||||
public class DriverJar extends Driver {
|
public class DriverJar extends Driver {
|
||||||
private static final String PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD";
|
private static final String PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD";
|
||||||
@@ -99,12 +86,14 @@ public class DriverJar extends Driver {
|
|||||||
logMessage("Skipping browsers download because `SELENIUM_REMOTE_URL` env variable is set");
|
logMessage("Skipping browsers download because `SELENIUM_REMOTE_URL` env variable is set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Chromium.preinstall(platformDir());
|
||||||
Path driver = driverPath();
|
Path driver = driverPath();
|
||||||
if (!Files.exists(driver)) {
|
if (!Files.exists(driver)) {
|
||||||
throw new RuntimeException("Failed to find driver: " + driver);
|
throw new RuntimeException("Failed to find driver: " + driver);
|
||||||
}
|
}
|
||||||
ProcessBuilder pb = createProcessBuilder();
|
ProcessBuilder pb = createProcessBuilder();
|
||||||
pb.command().add("install");
|
pb.command().add("install");
|
||||||
|
pb.command().add("chromium");
|
||||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||||
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||||
Process p = pb.start();
|
Process p = pb.start();
|
||||||
@@ -123,7 +112,6 @@ public class DriverJar extends Driver {
|
|||||||
return name.endsWith(".sh") || name.endsWith(".exe") || !name.contains(".");
|
return name.endsWith(".sh") || name.endsWith(".exe") || !name.contains(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private FileSystem initFileSystem(URI uri) throws IOException {
|
private FileSystem initFileSystem(URI uri) throws IOException {
|
||||||
try {
|
try {
|
||||||
return FileSystems.newFileSystem(uri, Collections.emptyMap());
|
return FileSystems.newFileSystem(uri, Collections.emptyMap());
|
||||||
@@ -131,10 +119,14 @@ public class DriverJar extends Driver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void extractDriverToTempDir() throws URISyntaxException, IOException {
|
|
||||||
|
public static URI getDriverResourceURI() throws URISyntaxException {
|
||||||
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
|
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
|
||||||
URI originalUri = classloader.getResource(
|
return classloader.getResource("driver/" + platformDir()).toURI();
|
||||||
"driver/" + platformDir()).toURI();
|
}
|
||||||
|
|
||||||
|
void extractDriverToTempDir() throws URISyntaxException, IOException {
|
||||||
|
URI originalUri = getDriverResourceURI();
|
||||||
URI uri = maybeExtractNestedJar(originalUri);
|
URI uri = maybeExtractNestedJar(originalUri);
|
||||||
|
|
||||||
// Create zip filesystem if loading from jar.
|
// Create zip filesystem if loading from jar.
|
||||||
@@ -72,7 +72,7 @@ object CFClearance {
|
|||||||
init {
|
init {
|
||||||
// Fix the default DriverJar issue by providing our own implementation
|
// Fix the default DriverJar issue by providing our own implementation
|
||||||
// ref: https://github.com/microsoft/playwright-java/issues/1138
|
// ref: https://github.com/microsoft/playwright-java/issues/1138
|
||||||
System.setProperty("playwright.driver.impl", "eu.kanade.tachiyomi.network.interceptor.DriverJar")
|
System.setProperty("playwright.driver.impl", "suwayomi.tachidesk.server.util.DriverJar")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveWithWebView(originalRequest: Request): Request {
|
fun resolveWithWebView(originalRequest: Request): Request {
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package suwayomi.tachidesk.server.util
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.contentOrNull
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import net.harawata.appdirs.AppDirsFactory
|
||||||
|
import java.nio.file.FileSystems
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.StandardCopyOption
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.io.path.absolutePathString
|
||||||
|
import kotlin.io.path.createDirectories
|
||||||
|
import kotlin.io.path.exists
|
||||||
|
import kotlin.io.path.notExists
|
||||||
|
import kotlin.streams.asSequence
|
||||||
|
|
||||||
|
object Chromium {
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@JvmStatic
|
||||||
|
fun preinstall(platformDir: String) {
|
||||||
|
val loader = Thread.currentThread().contextClassLoader
|
||||||
|
val resource = loader.getResource("driver/$platformDir/package/browsers.json") ?: return
|
||||||
|
val json = resource.openStream().use {
|
||||||
|
Json.decodeFromStream<JsonObject>(it)
|
||||||
|
}
|
||||||
|
val revision = json["browsers"]?.jsonArray
|
||||||
|
?.find { it.jsonObject["name"]?.jsonPrimitive?.contentOrNull == "chromium" }
|
||||||
|
?.jsonObject
|
||||||
|
?.get("revision")
|
||||||
|
?.jsonPrimitive
|
||||||
|
?.contentOrNull
|
||||||
|
?: return
|
||||||
|
|
||||||
|
val playwrightDir = AppDirsFactory.getInstance().getUserDataDir("ms-playwright", null, null)
|
||||||
|
val chromiumZip = Path(".").resolve("bin/chromium.zip")
|
||||||
|
val chromePath = Path(playwrightDir).resolve("chromium-$revision")
|
||||||
|
if (chromePath.exists() || chromiumZip.notExists()) return
|
||||||
|
chromePath.createDirectories()
|
||||||
|
|
||||||
|
FileSystems.newFileSystem(chromiumZip, null).use {
|
||||||
|
val src = it.getPath("/")
|
||||||
|
Files.walk(src)
|
||||||
|
.asSequence()
|
||||||
|
.forEach { source ->
|
||||||
|
Files.copy(
|
||||||
|
source,
|
||||||
|
chromePath.resolve(source.absolutePathString().removePrefix("/")),
|
||||||
|
StandardCopyOption.REPLACE_EXISTING
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user