Merge remote-tracking branch 'origin/master' into add-back-hsqldb

This commit is contained in:
Kavin 2023-10-26 16:18:55 +01:00
commit e45c7088dc
No known key found for this signature in database
GPG key ID: 6E4598CA5C92C41F
23 changed files with 73 additions and 66 deletions

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ 17 ]
java: [ 21 ]
steps:
- uses: actions/checkout@v4
@ -19,7 +19,7 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: temurin
distribution: zulu
cache: "gradle"
- name: Run Build
run: ./gradlew build

View file

@ -25,7 +25,7 @@ jobs:
dockerfile:
- Dockerfile.ci
- Dockerfile.azul.ci
- Dockerfile.openj9.ci
#- Dockerfile.openj9.ci
- Dockerfile.graalvm-jvm.ci
include:
- sleep: 20

View file

@ -17,8 +17,8 @@ jobs:
strategy:
matrix:
include:
- image: 1337kavin/piped:openj9
dockerfile: ./Dockerfile.openj9.ci
# - image: 1337kavin/piped:openj9
# dockerfile: ./Dockerfile.openj9.ci
- image: 1337kavin/piped:hotspot
dockerfile: ./Dockerfile.ci
- image: 1337kavin/piped:latest,1337kavin/piped:azul-zulu

View file

@ -15,11 +15,11 @@ jobs:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.sha }}
- name: set up JDK 17
- name: set up JDK 21
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
java-version: 21
distribution: zulu
cache: "gradle"
- name: Run Build
run: ./gradlew shadowJar
@ -39,7 +39,7 @@ jobs:
- testing/docker-compose.cockroachdb.yml
- testing/docker-compose.yugabytedb.yml
dockerfile:
- Dockerfile.ci
- Dockerfile.azul.ci
include:
- sleep: 20
- docker-compose-file: testing/docker-compose.cockroachdb.yml

View file

@ -9,11 +9,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
- name: set up JDK 21
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
java-version: 21
distribution: zulu
cache: "gradle"
- name: Run Build
run: ./gradlew shadowJar

View file

@ -1,4 +1,4 @@
FROM eclipse-temurin:17-jdk AS build
FROM eclipse-temurin:21-jdk AS build
WORKDIR /app/
@ -7,7 +7,7 @@ COPY . /app/
RUN --mount=type=cache,target=/root/.gradle/caches/ \
./gradlew shadowJar
FROM eclipse-temurin:17-jre
FROM eclipse-temurin:21-jre
RUN --mount=type=cache,target=/var/cache/apt/ \
apt-get update && \

View file

@ -1,4 +1,4 @@
FROM eclipse-temurin:17-jre
FROM eclipse-temurin:21-jre
RUN --mount=type=cache,target=/var/cache/apt/ \
apt-get update && \

View file

@ -1,4 +1,4 @@
FROM ghcr.io/graalvm/native-image:latest as build
FROM container-registry.oracle.com/graalvm/native-image:latest as build
WORKDIR /app/

View file

@ -1,4 +1,4 @@
FROM ghcr.io/graalvm/native-image:latest as build
FROM container-registry.oracle.com/graalvm/native-image:latest as build
RUN jlink \
--add-modules java.base,java.logging,java.sql,java.management,java.xml,java.naming,java.desktop,jdk.crypto.ec \

View file

@ -1,7 +1,6 @@
plugins {
id "com.github.johnrengelman.shadow" version "8.1.1"
id "java"
id "io.freefair.lombok" version "8.3"
id "eclipse"
}
@ -13,11 +12,11 @@ repositories {
dependencies {
implementation 'org.apache.commons:commons-lang3:3.13.0'
implementation 'org.apache.commons:commons-text:1.10.0'
implementation 'commons-io:commons-io:2.13.0'
implementation 'commons-io:commons-io:2.14.0'
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:5518112dce594bb4cd07d8ed3391bcc5e688f829'
implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:8cf9a4aef0919df2ef1baafd30ab5bfefefc0844'
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'
@ -42,9 +41,11 @@ 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.28.0'
implementation 'io.sentry:sentry:6.30.0'
implementation 'rocks.kavin:reqwest4j:1.0.12'
implementation 'io.minio:minio:8.5.6'
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
}
shadowJar {
@ -61,5 +62,5 @@ jar {
group = 'me.kavin.piped'
version = '1.0'
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://downloads.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://downloads.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

14
gradlew vendored
View file

@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

View file

@ -18,7 +18,7 @@ import org.hibernate.StatelessSession;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.localization.ContentCountry;
import org.schabi.newpipe.extractor.localization.Localization;
import org.schabi.newpipe.extractor.services.youtube.YoutubeThrottlingDecrypter;
import org.schabi.newpipe.extractor.services.youtube.YoutubeJavaScriptPlayerManager;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import java.util.*;
@ -53,17 +53,17 @@ public class Main {
System.exit(1);
}
Multithreading.runAsync(() -> new Thread(new SyncRunner(
Multithreading.runAsync(() -> Thread.ofVirtual().start(new SyncRunner(
new OkHttpClient.Builder().readTimeout(60, TimeUnit.SECONDS).build(),
MATRIX_SERVER,
MatrixHelper.MATRIX_TOKEN)
).start());
));
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.printf("ThrottlingCache: %o entries%n", YoutubeThrottlingDecrypter.getCacheSize());
YoutubeThrottlingDecrypter.clearCache();
System.out.printf("ThrottlingCache: %o entries%n", YoutubeJavaScriptPlayerManager.getThrottlingParametersCacheSize());
YoutubeJavaScriptPlayerManager.clearThrottlingParametersCache();
}
}, 0, TimeUnit.MINUTES.toMillis(60));

View file

@ -32,7 +32,7 @@ import static me.kavin.piped.consts.Constants.YOUTUBE_SERVICE;
import static me.kavin.piped.consts.Constants.mapper;
import static me.kavin.piped.utils.CollectionUtils.collectPreloadedTabs;
import static me.kavin.piped.utils.CollectionUtils.collectRelatedItems;
import static me.kavin.piped.utils.URLUtils.rewriteURL;
import static me.kavin.piped.utils.URLUtils.getLastThumbnail;
public class ChannelHandlers {
public static byte[] channelResponse(String channelPath) throws Exception {
@ -77,7 +77,7 @@ public class ChannelHandlers {
Multithreading.runAsync(() -> {
try {
MatrixHelper.sendEvent("video.piped.channel.info", new FederatedChannelInfo(
info.getId(), StringUtils.abbreviate(info.getName(), 100), info.getAvatarUrl(), info.isVerified())
info.getId(), StringUtils.abbreviate(info.getName(), 100), info.getAvatars().isEmpty() ? null : info.getAvatars().getLast().getUrl(), info.isVerified())
);
} catch (IOException e) {
throw new RuntimeException(e);
@ -93,7 +93,7 @@ public class ChannelHandlers {
if (channel != null) {
ChannelHelpers.updateChannel(s, channel, StringUtils.abbreviate(info.getName(), 100), info.getAvatarUrl(), info.isVerified());
ChannelHelpers.updateChannel(s, channel, StringUtils.abbreviate(info.getName(), 100), info.getAvatars().isEmpty() ? null : info.getAvatars().getLast().getUrl(), info.isVerified());
Set<String> ids = tabInfo.getRelatedItems()
.stream()
@ -159,8 +159,8 @@ public class ChannelHandlers {
}
}).toList();
final Channel channel = new Channel(info.getId(), info.getName(), rewriteURL(info.getAvatarUrl()),
rewriteURL(info.getBannerUrl()), info.getDescription(), info.getSubscriberCount(), info.isVerified(),
final Channel channel = new Channel(info.getId(), info.getName(), getLastThumbnail(info.getAvatars()),
getLastThumbnail(info.getBanners()), info.getDescription(), info.getSubscriberCount(), info.isVerified(),
nextpage, relatedStreams, tabs);
return mapper.writeValueAsBytes(channel);

View file

@ -30,8 +30,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static me.kavin.piped.consts.Constants.YOUTUBE_SERVICE;
import static me.kavin.piped.consts.Constants.mapper;
import static me.kavin.piped.utils.CollectionUtils.collectRelatedItems;
import static me.kavin.piped.utils.URLUtils.rewriteURL;
import static me.kavin.piped.utils.URLUtils.substringYouTube;
import static me.kavin.piped.utils.URLUtils.*;
public class PlaylistHandlers {
public static byte[] playlistResponse(String playlistId) throws Exception {
@ -60,10 +59,10 @@ public class PlaylistHandlers {
nextpage = mapper.writeValueAsString(page);
}
final Playlist playlist = new Playlist(info.getName(), rewriteURL(info.getThumbnailUrl()),
info.getDescription().getContent(), rewriteURL(info.getBannerUrl()), nextpage,
final Playlist playlist = new Playlist(info.getName(), getLastThumbnail(info.getThumbnails()),
info.getDescription().getContent(), getLastThumbnail(info.getBanners()), nextpage,
info.getUploaderName().isEmpty() ? null : info.getUploaderName(),
substringYouTube(info.getUploaderUrl()), rewriteURL(info.getUploaderAvatarUrl()),
substringYouTube(info.getUploaderUrl()), getLastThumbnail(info.getUploaderAvatars()),
(int) info.getStreamCount(), relatedStreams);
return mapper.writeValueAsBytes(playlist);

View file

@ -36,8 +36,7 @@ import java.util.concurrent.TimeoutException;
import static java.nio.charset.StandardCharsets.UTF_8;
import static me.kavin.piped.consts.Constants.YOUTUBE_SERVICE;
import static me.kavin.piped.consts.Constants.mapper;
import static me.kavin.piped.utils.URLUtils.rewriteURL;
import static me.kavin.piped.utils.URLUtils.substringYouTube;
import static me.kavin.piped.utils.URLUtils.*;
import static org.schabi.newpipe.extractor.NewPipe.getPreferredContentCountry;
import static org.schabi.newpipe.extractor.NewPipe.getPreferredLocalization;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
@ -342,10 +341,10 @@ public class StreamHandlers {
if (comment.getReplies() != null)
repliespage = mapper.writeValueAsString(comment.getReplies());
comments.add(new Comment(comment.getUploaderName(), rewriteURL(comment.getUploaderAvatarUrl()),
comments.add(new Comment(comment.getUploaderName(), getLastThumbnail(comment.getUploaderAvatars()),
comment.getCommentId(), Optional.ofNullable(comment.getCommentText()).map(Description::getContent).orElse(null), comment.getTextualUploadDate(),
substringYouTube(comment.getUploaderUrl()), repliespage, comment.getLikeCount(), comment.getReplyCount(),
comment.isHeartedByUploader(), comment.isPinned(), comment.isUploaderVerified()));
comment.isHeartedByUploader(), comment.isPinned(), comment.isUploaderVerified(), comment.hasCreatorReply(), comment.isChannelOwner()));
} catch (JsonProcessingException e) {
ExceptionHandler.handle(e);
}
@ -380,10 +379,10 @@ public class StreamHandlers {
if (comment.getReplies() != null)
repliespage = mapper.writeValueAsString(comment.getReplies());
comments.add(new Comment(comment.getUploaderName(), rewriteURL(comment.getUploaderAvatarUrl()),
comments.add(new Comment(comment.getUploaderName(), getLastThumbnail(comment.getUploaderAvatars()),
comment.getCommentId(), Optional.ofNullable(comment.getCommentText()).map(Description::getContent).orElse(null), comment.getTextualUploadDate(),
substringYouTube(comment.getUploaderUrl()), repliespage, comment.getLikeCount(), comment.getReplyCount(),
comment.isHeartedByUploader(), comment.isPinned(), comment.isUploaderVerified()));
comment.isHeartedByUploader(), comment.isPinned(), comment.isUploaderVerified(), comment.hasCreatorReply(), comment.isChannelOwner()));
} catch (JsonProcessingException e) {
ExceptionHandler.handle(e);
}

View file

@ -268,7 +268,7 @@ public class AuthPlaylistHandlers {
channel = DatabaseHelper.saveChannel(channelId);
}
video = new PlaylistVideo(videoId, info.getName(), info.getThumbnailUrl(), info.getDuration(), channel);
video = new PlaylistVideo(videoId, info.getName(), info.getThumbnails().getLast().getUrl(), info.getDuration(), channel);
var tr = s.beginTransaction();
try {
@ -402,7 +402,7 @@ public class AuthPlaylistHandlers {
PlaylistInfo info = PlaylistInfo.getInfo(url);
var playlist = new me.kavin.piped.utils.obj.db.Playlist(info.getName(), user, info.getThumbnailUrl());
var playlist = new me.kavin.piped.utils.obj.db.Playlist(info.getName(), user, info.getThumbnails().getLast().getUrl());
List<StreamInfoItem> videos = new ObjectArrayList<>(info.getRelatedItems());
@ -451,7 +451,7 @@ public class AuthPlaylistHandlers {
var channel = channelMap.get(channelId);
playlist.getVideos().add(videoMap.computeIfAbsent(videoId, (key) -> new PlaylistVideo(videoId, video.getName(), video.getThumbnailUrl(), video.getDuration(), channel)));
playlist.getVideos().add(videoMap.computeIfAbsent(videoId, (key) -> new PlaylistVideo(videoId, video.getName(), video.getThumbnails().getLast().getUrl(), video.getDuration(), channel)));
});
var tr = s.beginTransaction();

View file

@ -71,7 +71,7 @@ public class CollectionUtils {
return new Streams(info.getName(), info.getDescription().getContent(),
info.getTextualUploadDate(), info.getUploaderName(), substringYouTube(info.getUploaderUrl()),
rewriteURL(info.getUploaderAvatarUrl()), rewriteURL(info.getThumbnailUrl()), info.getDuration(),
getLastThumbnail(info.getUploaderAvatars()), getLastThumbnail(info.getThumbnails()), 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(),
@ -101,9 +101,9 @@ public class CollectionUtils {
StreamInfoItem item = (StreamInfoItem) o;
return new StreamItem(substringYouTube(item.getUrl()), item.getName(),
rewriteURL(item.getThumbnailUrl()),
getLastThumbnail(item.getThumbnails()),
item.getUploaderName(), substringYouTube(item.getUploaderUrl()),
rewriteURL(item.getUploaderAvatarUrl()), item.getTextualUploadDate(),
getLastThumbnail(item.getUploaderAvatars()), item.getTextualUploadDate(),
item.getShortDescription(), item.getDuration(),
item.getViewCount(), item.getUploadDate() != null ?
item.getUploadDate().offsetDateTime().toInstant().toEpochMilli() : -1,
@ -115,7 +115,7 @@ public class CollectionUtils {
PlaylistInfoItem item = (PlaylistInfoItem) o;
return new PlaylistItem(substringYouTube(item.getUrl()), item.getName(),
rewriteURL(item.getThumbnailUrl()),
getLastThumbnail(item.getThumbnails()),
item.getUploaderName(), substringYouTube(item.getUploaderUrl()),
item.isUploaderVerified(),
item.getPlaylistType().name(), item.getStreamCount());
@ -126,7 +126,7 @@ public class CollectionUtils {
ChannelInfoItem item = (ChannelInfoItem) o;
return new ChannelItem(substringYouTube(item.getUrl()), item.getName(),
rewriteURL(item.getThumbnailUrl()),
getLastThumbnail(item.getThumbnails()),
item.getDescription(), item.getSubscriberCount(), item.getStreamCount(),
item.isVerified());
}

View file

@ -192,7 +192,7 @@ public class DatabaseHelper {
}
var channel = new Channel(channelId, StringUtils.abbreviate(info.getName(), 100),
info.getAvatarUrl(), info.isVerified());
info.getAvatars().isEmpty() ? null : info.getAvatars().getLast().getUrl(), info.isVerified());
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var tr = s.beginTransaction();

View file

@ -5,7 +5,7 @@ import java.util.function.Supplier;
public class Multithreading {
private static final ExecutorService es = Executors.newCachedThreadPool();
private static final ExecutorService es = Executors.newVirtualThreadPerTaskExecutor();
private static final ExecutorService esLimited = Executors
.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8);
private static final ExecutorService esLimitedPubSub = Executors

View file

@ -2,12 +2,14 @@ package me.kavin.piped.utils;
import me.kavin.piped.consts.Constants;
import org.apache.commons.lang3.StringUtils;
import org.schabi.newpipe.extractor.Image;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class URLUtils {
@ -37,6 +39,10 @@ public class URLUtils {
return rewriteURL(old, Constants.IMAGE_PROXY_PART);
}
public static String getLastThumbnail(final List<Image> thumbnails) {
return thumbnails.isEmpty() ? null : rewriteURL(thumbnails.getLast().getUrl());
}
public static String rewriteVideoURL(final String old) {
return rewriteURL(old, Constants.PROXY_PART);
}

View file

@ -50,7 +50,7 @@ public class VideoHelpers {
if (!DatabaseHelper.doesVideoExist(s, info.getId())) {
Video video = new Video(info.getId(), info.getName(), info.getViewCount(), info.getDuration(),
Math.max(infoTime, time), info.getThumbnailUrl(), info.isShortFormContent(), channel);
Math.max(infoTime, time), info.getThumbnails().getLast().getUrl(), info.isShortFormContent(), channel);
insertVideo(video);
return;
@ -81,7 +81,7 @@ public class VideoHelpers {
boolean isShort = extractor.isShortFormContent() || isShort(extractor.getId());
Video video = new Video(extractor.getId(), extractor.getName(), extractor.getViewCount(), extractor.getLength(),
Math.max(infoTime, time), extractor.getThumbnailUrl(), isShort, channel);
Math.max(infoTime, time), extractor.getThumbnails().getLast().getUrl(), isShort, channel);
insertVideo(video);

View file

@ -4,10 +4,10 @@ public class Comment {
public String author, thumbnail, commentId, commentText, commentedTime, commentorUrl, repliesPage;
public int likeCount, replyCount;
public boolean hearted, pinned, verified;
public boolean hearted, pinned, verified, creatorReplied, channelOwner;
public Comment(String author, String thumbnail, String commentId, String commentText, String commentedTime,
String commentorUrl, String repliesPage, int likeCount, int replyCount, boolean hearted, boolean pinned, boolean verified) {
String commentorUrl, String repliesPage, int likeCount, int replyCount, boolean hearted, boolean pinned, boolean verified, boolean creatorReplied, boolean channelOwner) {
this.author = author;
this.thumbnail = thumbnail;
this.commentId = commentId;
@ -20,5 +20,7 @@ public class Comment {
this.hearted = hearted;
this.pinned = pinned;
this.verified = verified;
this.creatorReplied = creatorReplied;
this.channelOwner = channelOwner;
}
}