From 1dbda14335421453c89b8697a4579e1f1169bfbe Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 6 Jul 2023 14:54:45 +0100 Subject: [PATCH 01/32] Use an upsert statement for handling pubsub. --- .../java/me/kavin/piped/utils/PubSubHelper.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/PubSubHelper.java b/src/main/java/me/kavin/piped/utils/PubSubHelper.java index 23976b7..e1b6606 100644 --- a/src/main/java/me/kavin/piped/utils/PubSubHelper.java +++ b/src/main/java/me/kavin/piped/utils/PubSubHelper.java @@ -57,17 +57,14 @@ public class PubSubHelper { } public static void updatePubSub(String channelId) { - var pubsub = DatabaseHelper.getPubSubFromId(channelId); try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { - s.beginTransaction(); - if (pubsub == null) { - pubsub = new PubSub(channelId, System.currentTimeMillis()); - s.insert(pubsub); - } else { - pubsub.setSubbedAt(System.currentTimeMillis()); - s.update(pubsub); - } - s.getTransaction().commit(); + var tr = s.beginTransaction(); + s.createNativeMutationQuery("INSERT INTO pubsub (id, subbed_at) VALUES (?, ?) " + + "ON CONFLICT (id) DO UPDATE SET subbed_at = excluded.subbed_at") + .setParameter(1, channelId) + .setParameter(2, System.currentTimeMillis()) + .executeUpdate(); + tr.commit(); } } } From f9289a05d12f60f761ba53316963ed416435387d Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 6 Jul 2023 14:56:28 +0100 Subject: [PATCH 02/32] Use a limited threadpool for handling pubsub requests. --- .../java/me/kavin/piped/server/ServerLauncher.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/kavin/piped/server/ServerLauncher.java b/src/main/java/me/kavin/piped/server/ServerLauncher.java index 44e83ad..4626c08 100644 --- a/src/main/java/me/kavin/piped/server/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/server/ServerLauncher.java @@ -76,18 +76,21 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { .map(GET, "/webhooks/pubsub", AsyncServlet.ofBlocking(executor, request -> { var topic = request.getQueryParameter("hub.topic"); if (topic != null) - Multithreading.runAsync(() -> { + Multithreading.runAsyncLimited(() -> { String channelId = StringUtils.substringAfter(topic, "channel_id="); PubSubHelper.updatePubSub(channelId); }); - return HttpResponse.ok200().withPlainText(Objects.requireNonNull(request.getQueryParameter("hub.challenge"))); + + var challenge = request.getQueryParameter("hub.challenge"); + return HttpResponse.ok200() + .withPlainText(Objects.requireNonNullElse(challenge, "ok")); })).map(POST, "/webhooks/pubsub", AsyncServlet.ofBlocking(executor, request -> { try { SyndFeed feed = new SyndFeedInput().build( new InputSource(new ByteArrayInputStream(request.loadBody().getResult().asArray()))); - Multithreading.runAsync(() -> { + Multithreading.runAsyncLimited(() -> { for (var entry : feed.getEntries()) { String url = entry.getLinks().get(0).getHref(); String videoId = StringUtils.substring(url, -11); @@ -95,7 +98,7 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { if (DatabaseHelper.doesVideoExist(s, videoId)) continue; } - Multithreading.runAsync(() -> { + Multithreading.runAsyncLimited(() -> { try { Sentry.setExtra("videoId", videoId); var extractor = YOUTUBE_SERVICE.getStreamExtractor("https://youtube.com/watch?v=" + videoId); From 92249ca99177370f61e2ace7b160828983cdd6ab Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:52:24 +0000 Subject: [PATCH 03/32] Update dependency gradle to v8.2.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 83d5b95..c33e302 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://downloads.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://downloads.gradle.org/distributions/gradle-8.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From e676d97b3f127f8125033c5e548be867b8706f92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 14:54:39 +0000 Subject: [PATCH 04/32] Update dependency io.sentry:sentry to v6.25.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b20e990..09d6d26 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' - implementation 'io.sentry:sentry:6.25.0' + implementation 'io.sentry:sentry:6.25.1' implementation 'rocks.kavin:reqwest4j:1.0.6' implementation 'io.minio:minio:8.5.4' } From edf8e7f8e5e203a3f43758d6ffd2588b9cb0bc35 Mon Sep 17 00:00:00 2001 From: Yanick Date: Thu, 13 Jul 2023 14:53:00 +0200 Subject: [PATCH 05/32] add DISABLE_REGISTRATION to frontendProperties --- src/main/java/me/kavin/piped/consts/Constants.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/me/kavin/piped/consts/Constants.java b/src/main/java/me/kavin/piped/consts/Constants.java index b98298a..9620826 100644 --- a/src/main/java/me/kavin/piped/consts/Constants.java +++ b/src/main/java/me/kavin/piped/consts/Constants.java @@ -175,6 +175,7 @@ public class Constants { .map(JsonNodeFactory.instance::textNode).toList() ); frontendProperties.put("s3Enabled", S3_CLIENT != null); + frontendProperties.put("registrationDisabled", DISABLE_REGISTRATION); // transform hibernate properties for legacy configurations hibernateProperties.replace("hibernate.dialect", From 7b52736e837942ba67937a49dfa3048567e81f2c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 14 Jul 2023 09:45:49 +0000 Subject: [PATCH 06/32] Update dependency io.sentry:sentry to v6.25.2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 09d6d26..268c133 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' - implementation 'io.sentry:sentry:6.25.1' + implementation 'io.sentry:sentry:6.25.2' implementation 'rocks.kavin:reqwest4j:1.0.6' implementation 'io.minio:minio:8.5.4' } From 34efcb34019126305fed666270dfc5782eed8e73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:58:25 +0000 Subject: [PATCH 07/32] Update dependency org.springframework.security:spring-security-crypto to v6.1.2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 268c133..29410ae 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ dependencies { implementation 'org.hibernate:hibernate-core:6.2.5.Final' implementation 'org.hibernate:hibernate-hikaricp:6.2.5.Final' implementation 'com.zaxxer:HikariCP:5.0.1' - implementation 'org.springframework.security:spring-security-crypto:6.1.1' + implementation 'org.springframework.security:spring-security-crypto:6.1.2' implementation 'commons-logging:commons-logging:1.2' implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' From 369569d0f07dc4b29c080734ce8fc581110b23f0 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Wed, 19 Jul 2023 00:45:17 +0100 Subject: [PATCH 08/32] Implement batched fetching of dearrow content. --- .../me/kavin/piped/server/ServerLauncher.java | 18 +++++++ .../kavin/piped/utils/SponsorBlockUtils.java | 50 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/main/java/me/kavin/piped/server/ServerLauncher.java b/src/main/java/me/kavin/piped/server/ServerLauncher.java index 4626c08..85e0eac 100644 --- a/src/main/java/me/kavin/piped/server/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/server/ServerLauncher.java @@ -33,6 +33,7 @@ import org.xml.sax.InputSource; import java.io.ByteArrayInputStream; import java.net.InetSocketAddress; +import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -149,6 +150,23 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { } catch (Exception e) { return getErrorResponse(e, request.getPath()); } + })).map(GET, "/dearrow", AsyncServlet.ofBlocking(executor, request -> { + try { + var videoIds = getArray(request.getQueryParameter("videoIds")); + + return getJsonResponse( + SponsorBlockUtils.getDeArrowedInfo(List.of(videoIds)) + .thenApplyAsync(json -> { + try { + return mapper.writeValueAsBytes(json); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }).get(), + "public, max-age=3600"); + } catch (Exception e) { + return getErrorResponse(e, request.getPath()); + } })).map(GET, "/streams/:videoId", AsyncServlet.ofBlocking(executor, request -> { try { return getJsonResponse(StreamHandlers.streamsResponse(request.getPathParameter("videoId")), diff --git a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java index bfe580f..77ffbc6 100644 --- a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java +++ b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java @@ -1,5 +1,10 @@ package me.kavin.piped.utils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.NullNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import me.kavin.piped.consts.Constants; import me.kavin.piped.utils.resp.InvalidRequestResponse; import me.kavin.piped.utils.resp.SimpleErrorMessage; @@ -7,6 +12,9 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; import static me.kavin.piped.consts.Constants.mapper; @@ -46,4 +54,46 @@ public class SponsorBlockUtils { return null; } + public static CompletableFuture getDeArrowedInfo(List videoIds) { + ObjectNode objectNode = mapper.createObjectNode(); + + var futures = videoIds.stream() + .map(id -> getDeArrowedInfo(id).thenAcceptAsync(jsonNode -> objectNode.set(id, jsonNode.orElse(NullNode.getInstance())))) + .toArray(CompletableFuture[]::new); + + return CompletableFuture.allOf(futures) + .thenApplyAsync(v -> objectNode, Multithreading.getCachedExecutor()); + } + + private static CompletableFuture> getDeArrowedInfo(String videoId) { + + String hash = DigestUtils.sha256Hex(videoId); + + CompletableFuture> future = new CompletableFuture<>(); + + Multithreading.runAsync(() -> { + for (String url : Constants.SPONSORBLOCK_SERVERS) + try { + Optional optional = RequestUtils.sendGetJson(url + "/api/branding/" + URLUtils.silentEncode(hash.substring(0, 4))) + .thenApplyAsync(json -> json.has(videoId) ? Optional.of(json.get(videoId)) : Optional.empty()) + .get(); + + optional.ifPresent(jsonNode -> { + ArrayNode nodes = (ArrayNode) jsonNode.get("thumbnails"); + for (JsonNode node : nodes) { + ((ObjectNode) node).set("thumbnail", new TextNode(URLUtils.rewriteURL("https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=" + videoId + "&time=" + node.get("timestamp").asText()))); + } + }); + + + future.complete(optional); + return; + } catch (Exception ignored) { + } + future.completeExceptionally(new Exception("All SponsorBlock servers are down")); + }); + + return future; + + } } From fcc3c9daaf1de33604aa8b0a16efa24ee834a3a0 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Wed, 19 Jul 2023 01:00:06 +0100 Subject: [PATCH 09/32] Only add url to non-original thumnails. --- src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java index 77ffbc6..76c4c9a 100644 --- a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java +++ b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java @@ -81,7 +81,8 @@ public class SponsorBlockUtils { optional.ifPresent(jsonNode -> { ArrayNode nodes = (ArrayNode) jsonNode.get("thumbnails"); for (JsonNode node : nodes) { - ((ObjectNode) node).set("thumbnail", new TextNode(URLUtils.rewriteURL("https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=" + videoId + "&time=" + node.get("timestamp").asText()))); + if (!node.get("original").booleanValue()) + ((ObjectNode) node).set("thumbnail", new TextNode(URLUtils.rewriteURL("https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=" + videoId + "&time=" + node.get("timestamp").asText()))); } }); From b545b9359b3068a8b65e891a1793a946d4c67531 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 10:18:06 +0000 Subject: [PATCH 10/32] Update dependency io.sentry:sentry to v6.26.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 29410ae..231b179 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' - implementation 'io.sentry:sentry:6.25.2' + implementation 'io.sentry:sentry:6.26.0' implementation 'rocks.kavin:reqwest4j:1.0.6' implementation 'io.minio:minio:8.5.4' } From 5286cea23e81e4455fd69e08f5c698eef0df9df5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 00:25:21 +0000 Subject: [PATCH 11/32] Update hibernate core to v6.2.7.Final --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 231b179..883c267 100644 --- a/build.gradle +++ b/build.gradle @@ -31,8 +31,8 @@ dependencies { implementation 'io.activej:activej-launchers-http:5.5' implementation 'org.hsqldb:hsqldb:2.7.2' implementation 'org.postgresql:postgresql:42.6.0' - implementation 'org.hibernate:hibernate-core:6.2.5.Final' - implementation 'org.hibernate:hibernate-hikaricp:6.2.5.Final' + implementation 'org.hibernate:hibernate-core:6.2.7.Final' + implementation 'org.hibernate:hibernate-hikaricp:6.2.7.Final' implementation 'com.zaxxer:HikariCP:5.0.1' implementation 'org.springframework.security:spring-security-crypto:6.1.2' implementation 'commons-logging:commons-logging:1.2' From fa588aaf83a091d63b19fea74ece5738fc381fea Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Sat, 22 Jul 2023 05:39:22 +0100 Subject: [PATCH 12/32] Optimize threading when batch fetching DeArrow parallelly --- .../me/kavin/piped/server/ServerLauncher.java | 2 +- .../me/kavin/piped/utils/Multithreading.java | 9 ++- .../me/kavin/piped/utils/RequestUtils.java | 4 +- .../kavin/piped/utils/SponsorBlockUtils.java | 65 +++++++++++-------- 4 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/main/java/me/kavin/piped/server/ServerLauncher.java b/src/main/java/me/kavin/piped/server/ServerLauncher.java index 85e0eac..9c10d57 100644 --- a/src/main/java/me/kavin/piped/server/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/server/ServerLauncher.java @@ -155,7 +155,7 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { var videoIds = getArray(request.getQueryParameter("videoIds")); return getJsonResponse( - SponsorBlockUtils.getDeArrowedInfo(List.of(videoIds)) + SponsorBlockUtils.getDeArrowedInfo(videoIds) .thenApplyAsync(json -> { try { return mapper.writeValueAsBytes(json); diff --git a/src/main/java/me/kavin/piped/utils/Multithreading.java b/src/main/java/me/kavin/piped/utils/Multithreading.java index ccc54fd..2e4efd4 100644 --- a/src/main/java/me/kavin/piped/utils/Multithreading.java +++ b/src/main/java/me/kavin/piped/utils/Multithreading.java @@ -1,8 +1,6 @@ package me.kavin.piped.utils; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; import java.util.function.Supplier; public class Multithreading { @@ -12,11 +10,16 @@ public class Multithreading { .newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8); private static final ExecutorService esLimitedPubSub = Executors .newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + private static final ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors()); public static void runAsync(final Runnable runnable) { es.submit(runnable); } + public static void runAsyncTask(final ForkJoinTask task) { + forkJoinPool.submit(task); + } + public static void runAsyncLimited(final Runnable runnable) { esLimited.submit(runnable); } diff --git a/src/main/java/me/kavin/piped/utils/RequestUtils.java b/src/main/java/me/kavin/piped/utils/RequestUtils.java index d886418..f5c25b0 100644 --- a/src/main/java/me/kavin/piped/utils/RequestUtils.java +++ b/src/main/java/me/kavin/piped/utils/RequestUtils.java @@ -42,13 +42,13 @@ public class RequestUtils { } } - public static CompletableFuture sendGetJson(String url) throws Exception { + public static CompletableFuture sendGetJson(String url) { return ReqwestUtils.fetch(url, "GET", null, Map.of()).thenApply(Response::body).thenApplyAsync(resp -> { try { return mapper.readTree(resp); } catch (Exception e) { throw new RuntimeException("Failed to parse JSON", e); } - }, Multithreading.getCachedExecutor()); + }); } } diff --git a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java index 76c4c9a..1e9db55 100644 --- a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java +++ b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java @@ -12,10 +12,12 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import java.io.IOException; -import java.util.List; +import java.util.Arrays; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinTask; +import static me.kavin.piped.consts.Constants.SPONSORBLOCK_SERVERS; import static me.kavin.piped.consts.Constants.mapper; public class SponsorBlockUtils { @@ -54,47 +56,58 @@ public class SponsorBlockUtils { return null; } - public static CompletableFuture getDeArrowedInfo(List videoIds) { + public static CompletableFuture getDeArrowedInfo(String[] videoIds) { ObjectNode objectNode = mapper.createObjectNode(); - var futures = videoIds.stream() - .map(id -> getDeArrowedInfo(id).thenAcceptAsync(jsonNode -> objectNode.set(id, jsonNode.orElse(NullNode.getInstance())))) + var futures = Arrays.stream(videoIds) + .map(id -> getDeArrowedInfo(id, SPONSORBLOCK_SERVERS.toArray(new String[0])) + .thenAcceptAsync(jsonNode -> objectNode.set(id, jsonNode.orElse(NullNode.getInstance()))) + ) .toArray(CompletableFuture[]::new); return CompletableFuture.allOf(futures) .thenApplyAsync(v -> objectNode, Multithreading.getCachedExecutor()); } - private static CompletableFuture> getDeArrowedInfo(String videoId) { + private static CompletableFuture> getDeArrowedInfo(String videoId, String[] servers) { String hash = DigestUtils.sha256Hex(videoId); CompletableFuture> future = new CompletableFuture<>(); - Multithreading.runAsync(() -> { - for (String url : Constants.SPONSORBLOCK_SERVERS) - try { - Optional optional = RequestUtils.sendGetJson(url + "/api/branding/" + URLUtils.silentEncode(hash.substring(0, 4))) - .thenApplyAsync(json -> json.has(videoId) ? Optional.of(json.get(videoId)) : Optional.empty()) - .get(); - - optional.ifPresent(jsonNode -> { - ArrayNode nodes = (ArrayNode) jsonNode.get("thumbnails"); - for (JsonNode node : nodes) { - if (!node.get("original").booleanValue()) - ((ObjectNode) node).set("thumbnail", new TextNode(URLUtils.rewriteURL("https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=" + videoId + "&time=" + node.get("timestamp").asText()))); - } - }); - - - future.complete(optional); - return; - } catch (Exception ignored) { - } - future.completeExceptionally(new Exception("All SponsorBlock servers are down")); + var task = ForkJoinTask.adapt(() -> { + fetchDeArrowedCf(future, videoId, hash, servers); }); + Multithreading.runAsyncTask(task); + return future; } + + private static void fetchDeArrowedCf(CompletableFuture> future, String videoId, String hash, String[] servers) { + + var completableFuture = RequestUtils.sendGetJson(servers[0] + "/api/branding/" + URLUtils.silentEncode(hash.substring(0, 4))) + .thenApplyAsync(json -> json.has(videoId) ? Optional.of(json.get(videoId)) : Optional.empty()); + + completableFuture.thenAcceptAsync(optional -> optional.ifPresent(jsonNode -> { + ArrayNode nodes = (ArrayNode) jsonNode.get("thumbnails"); + for (JsonNode node : nodes) { + if (!node.get("original").booleanValue()) + ((ObjectNode) node).set("thumbnail", new TextNode(URLUtils.rewriteURL("https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=" + videoId + "&time=" + node.get("timestamp").asText()))); + } + })); + + + completableFuture.whenComplete((optional, throwable) -> { + if (throwable == null) + future.complete(optional); + else { + if (servers.length == 1) + future.completeExceptionally(new Exception("All SponsorBlock servers are down")); + else + fetchDeArrowedCf(future, videoId, hash, Arrays.copyOfRange(servers, 1, servers.length)); + } + }); + } } From c027fbefe828201b0d97bdaae7b09e97fad06f13 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:27:01 +0100 Subject: [PATCH 13/32] Handle PubSub better with a queue and actually waiting --- src/main/java/me/kavin/piped/Main.java | 36 ++++++++++++++++--- .../me/kavin/piped/utils/PubSubHelper.java | 28 ++++++++++----- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/main/java/me/kavin/piped/Main.java b/src/main/java/me/kavin/piped/Main.java index a8647c0..a5a8b57 100644 --- a/src/main/java/me/kavin/piped/Main.java +++ b/src/main/java/me/kavin/piped/Main.java @@ -23,6 +23,8 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt import rocks.kavin.reqwest4j.ReqwestUtils; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -102,15 +104,39 @@ public class Main { Collections.shuffle(channelIds); - channelIds.stream() - .parallel() - .forEach(id -> Multithreading.runAsyncLimitedPubSub(() -> { + var queue = new ConcurrentLinkedQueue<>(channelIds); + + System.out.println("PubSub: queue size - " + queue.size() + " channels"); + + for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) { + new Thread(() -> { + + Object o = new Object(); + + String channelId; + while ((channelId = queue.poll()) != null) { try { - PubSubHelper.subscribePubSub(id); + CompletableFuture future = PubSubHelper.subscribePubSub(channelId); + + if (future == null) + continue; + + future.whenComplete((resp, throwable) -> { + synchronized (o) { + o.notify(); + } + }); + + synchronized (o) { + o.wait(); + } + } catch (Exception e) { ExceptionHandler.handle(e); } - })); + } + }, "PubSub-" + i).start(); + } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/me/kavin/piped/utils/PubSubHelper.java b/src/main/java/me/kavin/piped/utils/PubSubHelper.java index e1b6606..f74bb5d 100644 --- a/src/main/java/me/kavin/piped/utils/PubSubHelper.java +++ b/src/main/java/me/kavin/piped/utils/PubSubHelper.java @@ -6,16 +6,21 @@ import okhttp3.FormBody; import okio.Buffer; import org.hibernate.StatelessSession; import rocks.kavin.reqwest4j.ReqwestUtils; +import rocks.kavin.reqwest4j.Response; +import javax.annotation.Nullable; import java.io.IOException; import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class PubSubHelper { - public static void subscribePubSub(String channelId) throws IOException { + + @Nullable + public static CompletableFuture subscribePubSub(String channelId) throws IOException { if (!ChannelHelpers.isValidId(channelId)) - return; + return null; PubSub pubsub = DatabaseHelper.getPubSubFromId(channelId); @@ -44,16 +49,21 @@ public class PubSubHelper { var buffer = new Buffer(); formBuilder.build().writeTo(buffer); - ReqwestUtils.fetch(Constants.PUBSUB_HUB_URL, "POST", buffer.readByteArray(), Map.of()) - .thenAccept(resp -> { - if (resp.status() != 202) + var completableFuture = ReqwestUtils.fetch(Constants.PUBSUB_HUB_URL, "POST", buffer.readByteArray(), Map.of()); + + completableFuture + .whenComplete((resp, e) -> { + if (e != null) { + ExceptionHandler.handle((Exception) e); + return; + } + if (resp != null && resp.status() != 202) System.out.println("Failed to subscribe: " + resp.status() + "\n" + new String(resp.body())); - }) - .exceptionally(e -> { - ExceptionHandler.handle((Exception) e); - return null; }); + + return completableFuture; } + return null; } public static void updatePubSub(String channelId) { From 1aac9fed1afdd19af1afabce55bd965afa4bcf91 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Tue, 25 Jul 2023 03:04:28 +0100 Subject: [PATCH 14/32] Implement randomTime for videos that don't exist in dearrow. --- src/main/java/me/kavin/piped/utils/Alea.java | 50 +++++++++++++++++++ .../kavin/piped/utils/SponsorBlockUtils.java | 18 +++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/me/kavin/piped/utils/Alea.java diff --git a/src/main/java/me/kavin/piped/utils/Alea.java b/src/main/java/me/kavin/piped/utils/Alea.java new file mode 100644 index 0000000..4e5059f --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/Alea.java @@ -0,0 +1,50 @@ +package me.kavin.piped.utils; + +public class Alea { + + private static final double NORM32 = 2.3283064365386963e-10; // 2^-32 + private double s0, s1, s2; + private int c = 1; + + public double next() { + double t = 2091639.0 * s0 + c * NORM32; // 2^-32 + s0 = s1; + s1 = s2; + return s2 = t - (c = (int) t); + } + + public Alea(String seed) { + s0 = mash(" "); + s1 = mash(" "); + s2 = mash(" "); + + s0 -= mash(seed); + + if (s0 < 0) + s0 += 1; + s1 -= mash(seed); + if (s1 < 0) + s1 += 1; + s2 -= mash(seed); + if (s2 < 0) + s2 += 1; + } + + private long n = 0xefc8249dL; + + public double mash(String x) { + double h; + + for (char c : x.toCharArray()) { + n += c; + h = 0.02519603282416938 * n; + n = (long) h; + h -= n; + h *= n; + n = (long) h; + h -= n; + n += h * 0x100000000L; + } + return n * 2.3283064365386963e-10; // 2^-32 + } +} diff --git a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java index 1e9db55..4151575 100644 --- a/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java +++ b/src/main/java/me/kavin/piped/utils/SponsorBlockUtils.java @@ -85,6 +85,15 @@ public class SponsorBlockUtils { } + private static final ObjectNode EMPTY_DEARROWED_INFO; + + static { + EMPTY_DEARROWED_INFO = mapper.createObjectNode(); + EMPTY_DEARROWED_INFO.putArray("titles"); + EMPTY_DEARROWED_INFO.putArray("thumbnails"); + EMPTY_DEARROWED_INFO.set("videoDuration", NullNode.getInstance()); + } + private static void fetchDeArrowedCf(CompletableFuture> future, String videoId, String hash, String[] servers) { var completableFuture = RequestUtils.sendGetJson(servers[0] + "/api/branding/" + URLUtils.silentEncode(hash.substring(0, 4))) @@ -98,6 +107,15 @@ public class SponsorBlockUtils { } })); + completableFuture = completableFuture.thenApplyAsync(optional -> { + if (optional.isEmpty()) { + var clone = EMPTY_DEARROWED_INFO.deepCopy(); + clone.put("randomTime", new Alea(videoId).next()); + return Optional.of(clone); + } else + return optional; + }); + completableFuture.whenComplete((optional, throwable) -> { if (throwable == null) From e450301f8fe5e73fba97526e6738e43dd1613702 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 09:45:51 +0000 Subject: [PATCH 15/32] Update dependency io.sentry:sentry to v6.27.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 883c267..edfdf66 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' - implementation 'io.sentry:sentry:6.26.0' + implementation 'io.sentry:sentry:6.27.0' implementation 'rocks.kavin:reqwest4j:1.0.6' implementation 'io.minio:minio:8.5.4' } From 0eeea271ce5372b33f56e78ae4e3ea9ebde7c03f Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 10:44:34 +0100 Subject: [PATCH 16/32] Add -XX:+HeapDumpOnOutOfMemoryError to hotspot images. --- Dockerfile | 2 +- Dockerfile.azul | 2 +- Dockerfile.azul.ci | 2 +- Dockerfile.ci | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index f0fa377..93bbb70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,4 +17,4 @@ COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar +CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar diff --git a/Dockerfile.azul b/Dockerfile.azul index d7d34cc..de258d0 100644 --- a/Dockerfile.azul +++ b/Dockerfile.azul @@ -17,4 +17,4 @@ COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar +CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar diff --git a/Dockerfile.azul.ci b/Dockerfile.azul.ci index d79d85f..4c8b7db 100644 --- a/Dockerfile.azul.ci +++ b/Dockerfile.azul.ci @@ -8,4 +8,4 @@ COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar +CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar diff --git a/Dockerfile.ci b/Dockerfile.ci index 525d716..8d58ec9 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -8,4 +8,4 @@ COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar +CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar From e66917d428eb53519cf23300dfd49ed2d6d6e01c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 04:04:24 +0000 Subject: [PATCH 17/32] Update dependency org.apache.commons:commons-lang3 to v3.13.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index edfdf66..a5b1d28 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ repositories { } dependencies { - implementation 'org.apache.commons:commons-lang3:3.12.0' + implementation 'org.apache.commons:commons-lang3:3.13.0' implementation 'org.apache.commons:commons-text:1.10.0' implementation 'commons-io:commons-io:2.12.0' implementation 'it.unimi.dsi:fastutil-core:8.5.12' From f4040772a21c2fd1d00396de34cc7bac2c840358 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:11:28 +0100 Subject: [PATCH 18/32] Suppress video insert errors on conflict --- .../me/kavin/piped/utils/VideoHelpers.java | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/VideoHelpers.java b/src/main/java/me/kavin/piped/utils/VideoHelpers.java index a305aa0..fef7add 100644 --- a/src/main/java/me/kavin/piped/utils/VideoHelpers.java +++ b/src/main/java/me/kavin/piped/utils/VideoHelpers.java @@ -6,7 +6,6 @@ import me.kavin.piped.consts.Constants; import me.kavin.piped.utils.obj.db.Video; import org.apache.commons.lang3.StringUtils; import org.hibernate.StatelessSession; -import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; @@ -49,14 +48,7 @@ public class VideoHelpers { Video video = new Video(info.getId(), info.getName(), info.getViewCount(), info.getDuration(), Math.max(infoTime, time), info.getThumbnailUrl(), info.isShortFormContent(), channel); - var tr = s.beginTransaction(); - try { - s.insert(video); - tr.commit(); - } catch (Exception e) { - tr.rollback(); - ExceptionHandler.handle(e); - } + insertVideo(video); return; } } @@ -87,14 +79,7 @@ public class VideoHelpers { Video video = new Video(extractor.getId(), extractor.getName(), extractor.getViewCount(), extractor.getLength(), Math.max(infoTime, time), extractor.getThumbnailUrl(), isShort, channel); - var tr = s.beginTransaction(); - try { - s.insert(video); - tr.commit(); - } catch (Exception e) { - tr.rollback(); - ExceptionHandler.handle(e); - } + insertVideo(video); } } @@ -169,4 +154,26 @@ public class VideoHelpers { return updated > 0; } } + + public static void insertVideo(Video video) { + try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { + var tr = s.beginTransaction(); + try { + s.createNativeMutationQuery("INSERT INTO videos (uploader_id,duration,is_short,thumbnail,title,uploaded,views,id) values " + + "(:uploader_id,:duration,:is_short,:thumbnail,:title,:uploaded,:views,:id) ON CONFLICT DO NOTHING") + .setParameter("uploader_id", video.getChannel()) + .setParameter("duration", video.getDuration()) + .setParameter("is_short", video.isShort()) + .setParameter("thumbnail", video.getThumbnail()) + .setParameter("title", video.getTitle()) + .setParameter("uploaded", video.getUploaded()) + .setParameter("views", video.getViews()) + .setParameter("id", video.getId()).executeUpdate(); + tr.commit(); + } catch (Exception e) { + tr.rollback(); + ExceptionHandler.handle(e); + } + } + } } From 88e38bd8a126e42c410670bc018f5109049e10bc Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:15:03 +0100 Subject: [PATCH 19/32] Fix video update on conflict insert --- src/main/java/me/kavin/piped/utils/VideoHelpers.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/VideoHelpers.java b/src/main/java/me/kavin/piped/utils/VideoHelpers.java index fef7add..3049c1d 100644 --- a/src/main/java/me/kavin/piped/utils/VideoHelpers.java +++ b/src/main/java/me/kavin/piped/utils/VideoHelpers.java @@ -159,8 +159,13 @@ public class VideoHelpers { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { var tr = s.beginTransaction(); try { - s.createNativeMutationQuery("INSERT INTO videos (uploader_id,duration,is_short,thumbnail,title,uploaded,views,id) values " + - "(:uploader_id,:duration,:is_short,:thumbnail,:title,:uploaded,:views,:id) ON CONFLICT DO NOTHING") + s.createNativeMutationQuery( + "INSERT INTO videos (uploader_id,duration,is_short,thumbnail,title,uploaded,views,id) values " + + "(:uploader_id,:duration,:is_short,:thumbnail,:title,:uploaded,:views,:id) ON CONFLICT (id) DO UPDATE SET " + + "duration = :duration," + + "title = :title," + + "views = :views" + ) .setParameter("uploader_id", video.getChannel()) .setParameter("duration", video.getDuration()) .setParameter("is_short", video.isShort()) From ca6e7cec7fc76d21f54c235ed712019e79be180d Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:42:21 +0100 Subject: [PATCH 20/32] Initialize Reqwest in Constants to prevent circular dependency --- src/main/java/me/kavin/piped/Main.java | 2 -- src/main/java/me/kavin/piped/consts/Constants.java | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/kavin/piped/Main.java b/src/main/java/me/kavin/piped/Main.java index a5a8b57..067f229 100644 --- a/src/main/java/me/kavin/piped/Main.java +++ b/src/main/java/me/kavin/piped/Main.java @@ -38,8 +38,6 @@ public class Main { YoutubeStreamExtractor.forceFetchAndroidClient(true); YoutubeStreamExtractor.forceFetchIosClient(true); - ReqwestUtils.init(Constants.REQWEST_PROXY); - Sentry.init(options -> { options.setDsn(Constants.SENTRY_DSN); options.setRelease(Constants.VERSION); diff --git a/src/main/java/me/kavin/piped/consts/Constants.java b/src/main/java/me/kavin/piped/consts/Constants.java index 9620826..8c3fc79 100644 --- a/src/main/java/me/kavin/piped/consts/Constants.java +++ b/src/main/java/me/kavin/piped/consts/Constants.java @@ -19,6 +19,7 @@ import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.localization.ContentCountry; +import rocks.kavin.reqwest4j.ReqwestUtils; import java.io.File; import java.io.FileReader; @@ -130,6 +131,7 @@ public class Constants { PUBSUB_URL = getProperty(prop, "PUBSUB_URL", PUBLIC_URL); PUBSUB_HUB_URL = getProperty(prop, "PUBSUB_HUB_URL", "https://pubsubhubbub.appspot.com/subscribe"); REQWEST_PROXY = getProperty(prop, "REQWEST_PROXY"); + ReqwestUtils.init(REQWEST_PROXY); FRONTEND_URL = getProperty(prop, "FRONTEND_URL", "https://piped.video"); COMPROMISED_PASSWORD_CHECK = Boolean.parseBoolean(getProperty(prop, "COMPROMISED_PASSWORD_CHECK", "true")); DISABLE_REGISTRATION = Boolean.parseBoolean(getProperty(prop, "DISABLE_REGISTRATION", "false")); From 8aefd7023de6458ca93ff8a12571eaaf960b2436 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:46:34 +0100 Subject: [PATCH 21/32] Use excluded in DO UPDATE SET --- src/main/java/me/kavin/piped/utils/VideoHelpers.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/VideoHelpers.java b/src/main/java/me/kavin/piped/utils/VideoHelpers.java index 3049c1d..7984246 100644 --- a/src/main/java/me/kavin/piped/utils/VideoHelpers.java +++ b/src/main/java/me/kavin/piped/utils/VideoHelpers.java @@ -162,9 +162,7 @@ public class VideoHelpers { s.createNativeMutationQuery( "INSERT INTO videos (uploader_id,duration,is_short,thumbnail,title,uploaded,views,id) values " + "(:uploader_id,:duration,:is_short,:thumbnail,:title,:uploaded,:views,:id) ON CONFLICT (id) DO UPDATE SET " + - "duration = :duration," + - "title = :title," + - "views = :views" + "duration = excluded.duration, title = excluded.title, views = excluded.views" ) .setParameter("uploader_id", video.getChannel()) .setParameter("duration", video.getDuration()) From 37b2fca2fd31f0a87a5648da5de2029e59c0a004 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 28 Jul 2023 11:50:21 +0100 Subject: [PATCH 22/32] Fix type mismatch error. --- src/main/java/me/kavin/piped/utils/VideoHelpers.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/VideoHelpers.java b/src/main/java/me/kavin/piped/utils/VideoHelpers.java index 7984246..6c80834 100644 --- a/src/main/java/me/kavin/piped/utils/VideoHelpers.java +++ b/src/main/java/me/kavin/piped/utils/VideoHelpers.java @@ -164,14 +164,15 @@ public class VideoHelpers { "(:uploader_id,:duration,:is_short,:thumbnail,:title,:uploaded,:views,:id) ON CONFLICT (id) DO UPDATE SET " + "duration = excluded.duration, title = excluded.title, views = excluded.views" ) - .setParameter("uploader_id", video.getChannel()) + .setParameter("uploader_id", video.getChannel().getUploaderId()) .setParameter("duration", video.getDuration()) .setParameter("is_short", video.isShort()) .setParameter("thumbnail", video.getThumbnail()) .setParameter("title", video.getTitle()) .setParameter("uploaded", video.getUploaded()) .setParameter("views", video.getViews()) - .setParameter("id", video.getId()).executeUpdate(); + .setParameter("id", video.getId()) + .executeUpdate(); tr.commit(); } catch (Exception e) { tr.rollback(); From 36edf34793e2f5cfad0731d44cc3ef5b347a4719 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 29 Jul 2023 11:19:56 +0200 Subject: [PATCH 23/32] add visibility, license and tags to streams info --- src/main/java/me/kavin/piped/utils/CollectionUtils.java | 5 ++--- src/main/java/me/kavin/piped/utils/obj/Streams.java | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/CollectionUtils.java b/src/main/java/me/kavin/piped/utils/CollectionUtils.java index 0c46fdf..b04fa1d 100644 --- a/src/main/java/me/kavin/piped/utils/CollectionUtils.java +++ b/src/main/java/me/kavin/piped/utils/CollectionUtils.java @@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import me.kavin.piped.utils.obj.*; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.extractor.channel.ChannelTabInfo; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; @@ -16,7 +15,6 @@ import java.util.List; import java.util.Locale; import java.util.Optional; -import static me.kavin.piped.consts.Constants.YOUTUBE_SERVICE; import static me.kavin.piped.utils.URLUtils.*; public class CollectionUtils { @@ -71,7 +69,8 @@ public class CollectionUtils { rewriteURL(info.getUploaderAvatarUrl()), rewriteURL(info.getThumbnailUrl()), info.getDuration(), info.getViewCount(), info.getLikeCount(), info.getDislikeCount(), info.getUploaderSubscriberCount(), info.isUploaderVerified(), audioStreams, videoStreams, relatedStreams, subtitles, livestream, rewriteVideoURL(info.getHlsUrl()), - rewriteVideoURL(info.getDashMpdUrl()), null, info.getCategory(), chapters, previewFrames); + rewriteVideoURL(info.getDashMpdUrl()), null, info.getCategory(), info.getLicence(), + info.getPrivacy().name().toLowerCase(), info.getTags(), chapters, previewFrames); } public static List collectRelatedItems(List items) { diff --git a/src/main/java/me/kavin/piped/utils/obj/Streams.java b/src/main/java/me/kavin/piped/utils/obj/Streams.java index 2567e89..f521b98 100644 --- a/src/main/java/me/kavin/piped/utils/obj/Streams.java +++ b/src/main/java/me/kavin/piped/utils/obj/Streams.java @@ -9,7 +9,9 @@ import java.util.List; public class Streams { public String title, description, uploadDate, uploader, uploaderUrl, uploaderAvatar, thumbnailUrl, hls, dash, - lbryId, category; + lbryId, category, license, visibility; + + public List tags; public boolean uploaderVerified; @@ -33,7 +35,7 @@ public class Streams { String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes, long uploaderSubscriberCount, boolean uploaderVerified, List audioStreams, List videoStreams, List relatedStreams, List subtitles, boolean livestream, String hls, String dash, - String lbryId, String category, List chapters, List previewFrames) { + String lbryId, String category, String license, String visibility, List tags, List chapters, List previewFrames) { this.title = title; this.description = description; this.uploadDate = uploadDate; @@ -58,5 +60,8 @@ public class Streams { this.chapters = chapters; this.previewFrames = previewFrames; this.category = category; + this.license = license; + this.tags = tags; + this.visibility = visibility; } } From adacbfe285c0ff764b24ce9fec4f7a97a6e2a464 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Thu, 3 Aug 2023 15:40:46 +0200 Subject: [PATCH 24/32] feat: support for meta info of videos --- .../me/kavin/piped/utils/CollectionUtils.java | 7 ++++++- .../java/me/kavin/piped/utils/obj/MetaInfo.java | 17 +++++++++++++++++ .../java/me/kavin/piped/utils/obj/Streams.java | 6 +++++- testing/api-test.sh | 3 +++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/main/java/me/kavin/piped/utils/obj/MetaInfo.java diff --git a/src/main/java/me/kavin/piped/utils/CollectionUtils.java b/src/main/java/me/kavin/piped/utils/CollectionUtils.java index b04fa1d..365048f 100644 --- a/src/main/java/me/kavin/piped/utils/CollectionUtils.java +++ b/src/main/java/me/kavin/piped/utils/CollectionUtils.java @@ -64,13 +64,18 @@ public class CollectionUtils { final List relatedStreams = collectRelatedItems(info.getRelatedItems()); + final List metaInfo = new ObjectArrayList<>(); + info.getMetaInfo().forEach(metaInfoItem -> { + metaInfo.add(new MetaInfo(metaInfoItem.getTitle(), metaInfoItem.getContent().getContent(), metaInfoItem.getUrls(), metaInfoItem.getUrlTexts())); + }); + return new Streams(info.getName(), info.getDescription().getContent(), info.getTextualUploadDate(), info.getUploaderName(), substringYouTube(info.getUploaderUrl()), rewriteURL(info.getUploaderAvatarUrl()), rewriteURL(info.getThumbnailUrl()), info.getDuration(), info.getViewCount(), info.getLikeCount(), info.getDislikeCount(), info.getUploaderSubscriberCount(), info.isUploaderVerified(), audioStreams, videoStreams, relatedStreams, subtitles, livestream, rewriteVideoURL(info.getHlsUrl()), rewriteVideoURL(info.getDashMpdUrl()), null, info.getCategory(), info.getLicence(), - info.getPrivacy().name().toLowerCase(), info.getTags(), chapters, previewFrames); + info.getPrivacy().name().toLowerCase(), info.getTags(), metaInfo, chapters, previewFrames); } public static List collectRelatedItems(List items) { diff --git a/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java b/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java new file mode 100644 index 0000000..b0915d6 --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java @@ -0,0 +1,17 @@ +package me.kavin.piped.utils.obj; + +import java.util.List; +import java.net.URL; + +public class MetaInfo { + public String title, description; + public List urls; + public List urlTexts; + + public MetaInfo(String title, String description, List urls, List urlTexts) { + this.title = title; + this.description = description; + this.urls = urls; + this.urlTexts = urlTexts; + } +} diff --git a/src/main/java/me/kavin/piped/utils/obj/Streams.java b/src/main/java/me/kavin/piped/utils/obj/Streams.java index f521b98..478a37b 100644 --- a/src/main/java/me/kavin/piped/utils/obj/Streams.java +++ b/src/main/java/me/kavin/piped/utils/obj/Streams.java @@ -13,6 +13,8 @@ public class Streams { public List tags; + public List metaInfo; + public boolean uploaderVerified; public long duration, views, likes, dislikes, uploaderSubscriberCount; @@ -35,7 +37,8 @@ public class Streams { String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes, long uploaderSubscriberCount, boolean uploaderVerified, List audioStreams, List videoStreams, List relatedStreams, List subtitles, boolean livestream, String hls, String dash, - String lbryId, String category, String license, String visibility, List tags, List chapters, List previewFrames) { + String lbryId, String category, String license, String visibility, List tags, List metaInfo, + List chapters, List previewFrames) { this.title = title; this.description = description; this.uploadDate = uploadDate; @@ -62,6 +65,7 @@ public class Streams { this.category = category; this.license = license; this.tags = tags; + this.metaInfo = metaInfo; this.visibility = visibility; } } diff --git a/testing/api-test.sh b/testing/api-test.sh index b0aee74..df3b9be 100755 --- a/testing/api-test.sh +++ b/testing/api-test.sh @@ -39,6 +39,9 @@ curl "${CURLOPTS[@]}" $HOST/clips/Ugkx71jS31nwsms_Cc65oi7yXF1mILflhhrO || exit 1 # Streams curl "${CURLOPTS[@]}" $HOST/streams/BtN-goy9VOY || exit 1 +# Streams with meta info +curl "${CURLOPTS[@]}" $HOST/streams/cJ9to6EmElQ || exit 1 + # Comments curl "${CURLOPTS[@]}" $HOST/comments/BtN-goy9VOY || exit 1 From 30806effc91ab1f38227a35653f47ee3e5a8dc45 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:50:46 +0100 Subject: [PATCH 25/32] Minor formatting changes. --- src/main/java/me/kavin/piped/utils/CollectionUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/CollectionUtils.java b/src/main/java/me/kavin/piped/utils/CollectionUtils.java index 365048f..bd09132 100644 --- a/src/main/java/me/kavin/piped/utils/CollectionUtils.java +++ b/src/main/java/me/kavin/piped/utils/CollectionUtils.java @@ -65,9 +65,9 @@ public class CollectionUtils { final List relatedStreams = collectRelatedItems(info.getRelatedItems()); final List metaInfo = new ObjectArrayList<>(); - info.getMetaInfo().forEach(metaInfoItem -> { - metaInfo.add(new MetaInfo(metaInfoItem.getTitle(), metaInfoItem.getContent().getContent(), metaInfoItem.getUrls(), metaInfoItem.getUrlTexts())); - }); + info.getMetaInfo().forEach(metaInfoItem -> metaInfo.add(new MetaInfo(metaInfoItem.getTitle(), metaInfoItem.getContent().getContent(), + metaInfoItem.getUrls(), metaInfoItem.getUrlTexts() + ))); return new Streams(info.getName(), info.getDescription().getContent(), info.getTextualUploadDate(), info.getUploaderName(), substringYouTube(info.getUploaderUrl()), From e48919d08b86126ff13f03ce8b4988237d36ba2c Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:45:47 +0100 Subject: [PATCH 26/32] Update NewPipeExtractor --- build.gradle | 2 +- .../java/me/kavin/piped/server/handlers/ChannelHandlers.java | 4 ++-- src/main/java/me/kavin/piped/utils/DatabaseHelper.java | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index a5b1d28..0d72955 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation 'it.unimi.dsi:fastutil-core:8.5.12' implementation 'commons-codec:commons-codec:1.16.0' implementation 'org.bouncycastle:bcprov-jdk15on:1.70' - implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:bdd1366285614f56a245e3baceb26fb8864bda27' + implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:ea9105d70a396672e353265924622c05e5be0b6b' implementation 'com.github.FireMasterK:nanojson:01934924442edda6952f3bedf80ba9e969cba8bc' implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.2' diff --git a/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java b/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java index 2606477..e086df9 100644 --- a/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java +++ b/src/main/java/me/kavin/piped/server/handlers/ChannelHandlers.java @@ -15,10 +15,10 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.channel.ChannelTabInfo; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.linkhandler.ChannelTabs; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfoItem; diff --git a/src/main/java/me/kavin/piped/utils/DatabaseHelper.java b/src/main/java/me/kavin/piped/utils/DatabaseHelper.java index a168c7c..9b9ae91 100644 --- a/src/main/java/me/kavin/piped/utils/DatabaseHelper.java +++ b/src/main/java/me/kavin/piped/utils/DatabaseHelper.java @@ -10,9 +10,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.hibernate.SharedSessionContract; import org.hibernate.StatelessSession; -import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.channel.ChannelTabInfo; +import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.stream.StreamInfoItem; From 631ec8c0c47b73cca8a903dc109297bb01a62cb1 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:07:38 +0100 Subject: [PATCH 27/32] Update nanojson Closes https://github.com/TeamPiped/Piped/issues/2756 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0d72955..0937e8f 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ dependencies { implementation 'commons-codec:commons-codec:1.16.0' implementation 'org.bouncycastle:bcprov-jdk15on:1.70' implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:ea9105d70a396672e353265924622c05e5be0b6b' - implementation 'com.github.FireMasterK:nanojson:01934924442edda6952f3bedf80ba9e969cba8bc' + implementation 'com.github.FireMasterK:nanojson:9f4af3b739cc13f3d0d9d4b758bbe2b2ae7119d7' implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' From af9ce59b4c9270668b50ae0d8dce74d8a0f31ba4 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:13:08 +0100 Subject: [PATCH 28/32] Update NewPipeExtractor --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0937e8f..658afd4 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation 'it.unimi.dsi:fastutil-core:8.5.12' implementation 'commons-codec:commons-codec:1.16.0' implementation 'org.bouncycastle:bcprov-jdk15on:1.70' - implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:ea9105d70a396672e353265924622c05e5be0b6b' + implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:88ceba0da4a48b5f4ffecb3b5b2f36f95ec53afe' implementation 'com.github.FireMasterK:nanojson:9f4af3b739cc13f3d0d9d4b758bbe2b2ae7119d7' implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.2' From 0e3010cabc138f776734e990d5288cec02776822 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:13:22 +0000 Subject: [PATCH 29/32] fix(deps): update dependency rocks.kavin:reqwest4j to v1.0.7 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0937e8f..b6f6a5c 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' implementation 'io.sentry:sentry:6.27.0' - implementation 'rocks.kavin:reqwest4j:1.0.6' + implementation 'rocks.kavin:reqwest4j:1.0.7' implementation 'io.minio:minio:8.5.4' } From 0753e30ea595ddc14332aa448eeefdfce8a88aa0 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 4 Aug 2023 15:56:37 +0100 Subject: [PATCH 30/32] Add no args constructor to fix matrix deserialization issues. --- .../java/me/kavin/piped/utils/obj/MetaInfo.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java b/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java index b0915d6..53bf2eb 100644 --- a/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java +++ b/src/main/java/me/kavin/piped/utils/obj/MetaInfo.java @@ -1,17 +1,15 @@ package me.kavin.piped.utils.obj; -import java.util.List; -import java.net.URL; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import java.net.URL; +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor public class MetaInfo { public String title, description; public List urls; public List urlTexts; - - public MetaInfo(String title, String description, List urls, List urlTexts) { - this.title = title; - this.description = description; - this.urls = urls; - this.urlTexts = urlTexts; - } } From 0d9d1be979d060850be81e55a1c73a144d7fa0c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:59:07 +0000 Subject: [PATCH 31/32] fix(deps): update dependency io.sentry:sentry to v6.28.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e4547a5..57c544d 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(platform("com.squareup.okhttp3:okhttp-bom:4.11.0")) implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp-brotli' - implementation 'io.sentry:sentry:6.27.0' + implementation 'io.sentry:sentry:6.28.0' implementation 'rocks.kavin:reqwest4j:1.0.7' implementation 'io.minio:minio:8.5.4' } From 1d9dbe32f14b7f7c2ba28168fc031e10e5f8b562 Mon Sep 17 00:00:00 2001 From: Kavin <20838718+FireMasterK@users.noreply.github.com> Date: Fri, 4 Aug 2023 16:25:52 +0100 Subject: [PATCH 32/32] Add common hotspot entrypoint. --- Dockerfile | 4 +++- Dockerfile.azul | 4 +++- Dockerfile.azul.ci | 4 +++- Dockerfile.ci | 4 +++- hotspot-entrypoint.sh | 5 +++++ 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100755 hotspot-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 93bbb70..922e831 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,10 +11,12 @@ FROM eclipse-temurin:17-jre WORKDIR /app/ +COPY hotspot-entrypoint.sh / + COPY --from=build /app/build/libs/piped-1.0-all.jar /app/piped.jar COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar +ENTRYPOINT ["/hotspot-entrypoint.sh"] diff --git a/Dockerfile.azul b/Dockerfile.azul index de258d0..b376720 100644 --- a/Dockerfile.azul +++ b/Dockerfile.azul @@ -11,10 +11,12 @@ FROM azul/zulu-openjdk:17-jre-headless-latest WORKDIR /app/ +COPY hotspot-entrypoint.sh / + COPY --from=build /app/build/libs/piped-1.0-all.jar /app/piped.jar COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar +ENTRYPOINT ["/hotspot-entrypoint.sh"] diff --git a/Dockerfile.azul.ci b/Dockerfile.azul.ci index 4c8b7db..6c7c24d 100644 --- a/Dockerfile.azul.ci +++ b/Dockerfile.azul.ci @@ -2,10 +2,12 @@ FROM azul/zulu-openjdk:17-jre-headless-latest WORKDIR /app/ +COPY hotspot-entrypoint.sh / + COPY ./piped.jar /app/piped.jar COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar +ENTRYPOINT ["/hotspot-entrypoint.sh"] diff --git a/Dockerfile.ci b/Dockerfile.ci index 8d58ec9..94acf71 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -2,10 +2,12 @@ FROM eclipse-temurin:17-jre WORKDIR /app/ +COPY hotspot-entrypoint.sh / + COPY ./piped.jar /app/piped.jar COPY VERSION . EXPOSE 8080 -CMD java -server -Xmx1G -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -Xshare:on -jar /app/piped.jar +ENTRYPOINT ["/hotspot-entrypoint.sh"] diff --git a/hotspot-entrypoint.sh b/hotspot-entrypoint.sh new file mode 100755 index 0000000..eea1684 --- /dev/null +++ b/hotspot-entrypoint.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +MAX_MEMORY=${MAX_MEMORY:-1G} + +java -server -Xmx"$MAX_MEMORY" -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+OptimizeStringConcat -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+UseNUMA -XX:+UseG1GC -jar /app/piped.jar