From f28d40dffe1bf6421284d66a96ea607ed4d73cd4 Mon Sep 17 00:00:00 2001 From: FireMasterK <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 10 Feb 2022 14:56:58 +0000 Subject: [PATCH 1/2] Add support for extracting videoId from clipId. --- .../java/me/kavin/piped/ServerLauncher.java | 7 +++++ .../me/kavin/piped/utils/ResponseHelper.java | 29 +++++++++++++++++-- .../utils/resp/VideoResolvedResponse.java | 10 +++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/kavin/piped/utils/resp/VideoResolvedResponse.java diff --git a/src/main/java/me/kavin/piped/ServerLauncher.java b/src/main/java/me/kavin/piped/ServerLauncher.java index 71893c6..8a738fc 100644 --- a/src/main/java/me/kavin/piped/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/ServerLauncher.java @@ -82,6 +82,13 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { } catch (Exception e) { return getErrorResponse(e, request.getPath()); } + })).map(GET, "/clips/:clipId", AsyncServlet.ofBlocking(executor, request -> { + try { + return getJsonResponse(ResponseHelper.resolveClipId(request.getPathParameter("clipId")), + "public, max-age=31536000, immutable"); + } catch (Exception e) { + return getErrorResponse(e, request.getPath()); + } })).map(GET, "/channel/:channelId", AsyncServlet.ofBlocking(executor, request -> { try { return getJsonResponse( diff --git a/src/main/java/me/kavin/piped/utils/ResponseHelper.java b/src/main/java/me/kavin/piped/utils/ResponseHelper.java index 296ca1f..f00928e 100644 --- a/src/main/java/me/kavin/piped/utils/ResponseHelper.java +++ b/src/main/java/me/kavin/piped/utils/ResponseHelper.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.Scheduler; +import com.grack.nanojson.JsonObject; +import com.grack.nanojson.JsonWriter; import com.rometools.rome.feed.synd.*; import com.rometools.rome.io.FeedException; import com.rometools.rome.io.SyndFeedOutput; @@ -41,6 +43,7 @@ import org.schabi.newpipe.extractor.search.SearchInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; +import org.schabi.newpipe.extractor.utils.JsonUtils; import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -48,14 +51,18 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import static java.nio.charset.StandardCharsets.UTF_8; import static me.kavin.piped.consts.Constants.YOUTUBE_SERVICE; import static me.kavin.piped.utils.URLUtils.rewriteURL; import static me.kavin.piped.utils.URLUtils.substringYouTube; +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; +import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder; public class ResponseHelper { @@ -162,6 +169,22 @@ public class ResponseHelper { } + public static byte[] resolveClipId(String clipId) throws Exception { + + final byte[] body = JsonWriter.string(prepareDesktopJsonBuilder( + getPreferredLocalization(), getPreferredContentCountry()) + .value("url", "https://www.youtube.com/clip/" + clipId) + .done()) + .getBytes(UTF_8); + + final JsonObject jsonResponse = getJsonPostResponse("navigation/resolve_url", + body, getPreferredLocalization()); + + final String videoId = JsonUtils.getString(jsonResponse, "endpoint.watchEndpoint.videoId"); + + return Constants.mapper.writeValueAsBytes(new VideoResolvedResponse(videoId)); + } + public static byte[] channelResponse(String channelPath) throws Exception { final ChannelInfo info = ChannelInfo.getInfo("https://youtube.com/" + channelPath); @@ -336,7 +359,7 @@ public class ResponseHelper { feed.setEntries(entries); - return new SyndFeedOutput().outputString(feed).getBytes(StandardCharsets.UTF_8); + return new SyndFeedOutput().outputString(feed).getBytes(UTF_8); } @@ -789,7 +812,7 @@ public class ResponseHelper { s.close(); - return new SyndFeedOutput().outputString(feed).getBytes(StandardCharsets.UTF_8); + return new SyndFeedOutput().outputString(feed).getBytes(UTF_8); } s.close(); diff --git a/src/main/java/me/kavin/piped/utils/resp/VideoResolvedResponse.java b/src/main/java/me/kavin/piped/utils/resp/VideoResolvedResponse.java new file mode 100644 index 0000000..3c89d0b --- /dev/null +++ b/src/main/java/me/kavin/piped/utils/resp/VideoResolvedResponse.java @@ -0,0 +1,10 @@ +package me.kavin.piped.utils.resp; + +public class VideoResolvedResponse { + + public String videoId; + + public VideoResolvedResponse(String videoId) { + this.videoId = videoId; + } +} From a538028c515fef20c07a5bed56b447c6d5eb5ba1 Mon Sep 17 00:00:00 2001 From: FireMasterK <20838718+FireMasterK@users.noreply.github.com> Date: Thu, 10 Feb 2022 15:00:03 +0000 Subject: [PATCH 2/2] Add test for Clips. --- testing/api-test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/api-test.sh b/testing/api-test.sh index 023a1f7..d59ab2a 100755 --- a/testing/api-test.sh +++ b/testing/api-test.sh @@ -22,6 +22,9 @@ curl ${CURLOPTS[@]} $HOST/playlists/PLQSoWXSpjA3-egtFq45DcUydZ885W7MTT || exit 1 PLAYLIST_NEXTPAGE=$(curl -s -o - -f $HOST/playlists/PLQSoWXSpjA3-egtFq45DcUydZ885W7MTT | jq -r .nextpage) curl ${CURLOPTS[@]} $HOST/nextpage/playlists/UCsXVk37bltHxD1rDPwtNM8Q -G --data-urlencode "nextpage=$PLAYLIST_NEXTPAGE" || exit 1 +# Clips +curl ${CURLOPTS[@]} $HOST/clips/Ugkx71jS31nwsms_Cc65oi7yXF1mILflhhrO || exit 1 + # Streams curl ${CURLOPTS[@]} $HOST/streams/BtN-goy9VOY || exit 1