Piped-Backend/src/main/java/me/kavin/piped/utils/ResponseHelper.java

477 lines
21 KiB
Java
Raw Normal View History

2020-11-12 21:19:45 +00:00
package me.kavin.piped.utils;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.List;
import java.util.concurrent.CompletableFuture;
2020-11-12 21:19:45 +00:00
import java.util.concurrent.TimeUnit;
import org.apache.commons.codec.binary.Base64;
2020-11-25 05:26:25 +00:00
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
2020-11-12 21:19:45 +00:00
import org.json.JSONObject;
2020-12-14 07:11:42 +00:00
import org.schabi.newpipe.extractor.InfoItem;
2020-11-25 05:26:25 +00:00
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage;
import org.schabi.newpipe.extractor.Page;
2020-11-12 21:19:45 +00:00
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.comments.CommentsInfo;
2021-04-03 15:08:32 +00:00
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
2020-11-12 21:19:45 +00:00
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
2021-01-04 05:47:28 +00:00
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
2020-12-09 13:30:42 +00:00
import org.schabi.newpipe.extractor.search.SearchInfo;
2020-11-12 21:19:45 +00:00
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
2020-11-25 05:26:25 +00:00
import com.fasterxml.jackson.core.JsonProcessingException;
2020-11-12 21:19:45 +00:00
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import me.kavin.piped.consts.Constants;
2021-02-24 09:52:29 +00:00
import me.kavin.piped.ipfs.IPFS;
2020-11-12 21:19:45 +00:00
import me.kavin.piped.utils.obj.Channel;
2021-02-24 09:52:29 +00:00
import me.kavin.piped.utils.obj.ChapterSegment;
2021-04-03 15:08:32 +00:00
import me.kavin.piped.utils.obj.Comment;
import me.kavin.piped.utils.obj.CommentsPage;
2020-11-25 05:26:25 +00:00
import me.kavin.piped.utils.obj.PipedStream;
2021-01-04 05:47:28 +00:00
import me.kavin.piped.utils.obj.Playlist;
2020-12-14 07:11:42 +00:00
import me.kavin.piped.utils.obj.SearchResults;
2020-11-12 21:19:45 +00:00
import me.kavin.piped.utils.obj.StreamItem;
import me.kavin.piped.utils.obj.Streams;
2021-01-04 05:47:28 +00:00
import me.kavin.piped.utils.obj.StreamsPage;
2020-11-12 21:19:45 +00:00
import me.kavin.piped.utils.obj.Subtitle;
2020-12-09 13:30:42 +00:00
import me.kavin.piped.utils.obj.search.SearchItem;
import me.kavin.piped.utils.obj.search.SearchStream;
2020-11-12 21:19:45 +00:00
public class ResponseHelper {
public static final LoadingCache<String, CommentsInfo> commentsCache = Caffeine.newBuilder()
2021-02-24 09:52:29 +00:00
.expireAfterWrite(1, TimeUnit.HOURS).maximumSize(1000)
.build(key -> CommentsInfo.getInfo("https://www.youtube.com/watch?v=" + key));
2020-11-12 21:19:45 +00:00
public static final byte[] streamsResponse(String videoId) throws Exception {
2021-02-24 09:52:29 +00:00
CompletableFuture<StreamInfo> futureStream = CompletableFuture.supplyAsync(() -> {
try {
return StreamInfo.getInfo("https://www.youtube.com/watch?v=" + videoId);
} catch (Exception e) {
ExceptionUtils.rethrow(e);
}
return null;
});
CompletableFuture<String> futureLBRY = CompletableFuture.supplyAsync(() -> {
try {
return getLBRYStreamURL(videoId);
} catch (Exception e) {
ExceptionUtils.rethrow(e);
}
return null;
});
final List<Subtitle> subtitles = new ObjectArrayList<>();
final StreamInfo info = futureStream.get(10, TimeUnit.SECONDS);
2021-02-24 09:52:29 +00:00
// System.out.println(Constants.mapper.writeValueAsString(info.getStreamSegments()));
2021-04-21 14:22:58 +00:00
info.getSubtitles()
.forEach(subtitle -> subtitles.add(new Subtitle(rewriteURL(subtitle.getUrl()),
subtitle.getFormat().getMimeType(), subtitle.getDisplayLanguageName(),
subtitle.getLanguageTag(), subtitle.isAutoGenerated())));
2021-02-24 09:52:29 +00:00
final List<PipedStream> videoStreams = new ObjectArrayList<>();
final List<PipedStream> audioStreams = new ObjectArrayList<>();
final String lbryURL = futureLBRY.get(10, TimeUnit.SECONDS);
2021-02-24 09:52:29 +00:00
if (lbryURL != null)
videoStreams.add(new PipedStream(lbryURL, "MP4", "LBRY", "video/mp4", false));
final String hls;
boolean livestream = false;
if ((hls = info.getHlsUrl()) != null && !hls.isEmpty())
livestream = true;
if (hls != null) {
java.util.stream.Stream<String> resp = Constants.h2client
.send(HttpRequest.newBuilder(URI.create(hls)).GET().build(), BodyHandlers.ofLines()).body();
ObjectArrayList<String> lines = new ObjectArrayList<>();
resp.forEach(line -> lines.add(line));
for (int i = lines.size() - 1; i > 2; i--) {
String line = lines.get(i);
if (line.startsWith("https://manifest.googlevideo.com")) {
String prevLine = lines.get(i - 1);
String height = StringUtils.substringBetween(prevLine, "RESOLUTION=", ",").split("x")[1];
int fps = Integer.parseInt(StringUtils.substringBetween(prevLine, "FRAME-RATE=", ","));
String quality = height + "p";
if (fps > 30)
quality += fps;
videoStreams.add(new PipedStream(line, "HLS", quality, "application/x-mpegURL", false));
}
}
}
if (!livestream) {
info.getVideoOnlyStreams().forEach(stream -> videoStreams.add(new PipedStream(rewriteURL(stream.getUrl()),
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType(), true,
stream.getBitrate(), stream.getInitStart(), stream.getInitEnd(), stream.getIndexStart(),
stream.getIndexEnd(), stream.getCodec(), stream.getWidth(), stream.getHeight(), 30)));
info.getVideoStreams()
.forEach(stream -> videoStreams
.add(new PipedStream(rewriteURL(stream.getUrl()), String.valueOf(stream.getFormat()),
stream.getResolution(), stream.getFormat().getMimeType(), false)));
info.getAudioStreams()
.forEach(stream -> audioStreams.add(new PipedStream(rewriteURL(stream.getUrl()),
String.valueOf(stream.getFormat()), stream.getAverageBitrate() + " kbps",
stream.getFormat().getMimeType(), false, stream.getBitrate(), stream.getInitStart(),
stream.getInitEnd(), stream.getIndexStart(), stream.getIndexEnd(), stream.getCodec())));
}
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
info.getRelatedItems().forEach(o -> {
2021-02-24 09:52:29 +00:00
StreamInfoItem item = (StreamInfoItem) o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
List<ChapterSegment> segments = new ObjectArrayList<>();
info.getStreamSegments().forEach(
segment -> segments.add(new ChapterSegment(segment.getTitle(), segment.getStartTimeSeconds())));
final Streams streams = new Streams(info.getName(), info.getDescription().getContent(),
info.getTextualUploadDate(), info.getUploaderName(), info.getUploaderUrl().substring(23),
rewriteURL(info.getUploaderAvatarUrl()), rewriteURL(info.getThumbnailUrl()), info.getDuration(),
info.getViewCount(), info.getLikeCount(), info.getDislikeCount(), audioStreams, videoStreams,
relatedStreams, subtitles, livestream, hls);
return Constants.mapper.writeValueAsBytes(streams);
2020-11-12 21:19:45 +00:00
}
2021-02-24 09:52:29 +00:00
public static final byte[] channelResponse(String channelId) throws Exception {
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
final ChannelInfo info = ChannelInfo.getInfo("https://youtube.com/channel/" + channelId);
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
info.getRelatedItems().forEach(o -> {
StreamInfoItem item = o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
2020-11-12 21:19:45 +00:00
String nextpage = null, body = null;
if (info.hasNextPage()) {
Page page = info.getNextPage();
nextpage = page.getUrl();
body = Base64.encodeBase64String(info.getNextPage().getBody());
}
2020-11-25 05:26:25 +00:00
2021-02-24 09:52:29 +00:00
final Channel channel = new Channel(info.getId(), info.getName(), rewriteURL(info.getAvatarUrl()),
rewriteURL(info.getBannerUrl()), info.getDescription(), nextpage, body, relatedStreams);
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
IPFS.publishData(channel);
return Constants.mapper.writeValueAsBytes(channel);
2020-11-12 21:19:45 +00:00
}
public static final byte[] channelPageResponse(String channelId, String url, String body_req)
2021-02-24 09:52:29 +00:00
throws IOException, ExtractionException, InterruptedException {
2020-11-25 05:26:25 +00:00
2021-03-30 09:22:36 +00:00
InfoItemsPage<StreamInfoItem> info = ChannelInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
"https://youtube.com/channel/" + channelId, new Page(url, Base64.decodeBase64(body_req)));
2020-11-25 05:26:25 +00:00
2021-02-24 09:52:29 +00:00
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
2020-11-25 05:26:25 +00:00
2021-03-30 09:22:36 +00:00
info.getItems().forEach(o -> {
2021-02-24 09:52:29 +00:00
StreamInfoItem item = o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
2020-11-25 05:26:25 +00:00
String nextpage = null, body = null;
2021-03-30 09:22:36 +00:00
if (info.hasNextPage()) {
Page page = info.getNextPage();
nextpage = page.getUrl();
body = Base64.encodeBase64String(info.getNextPage().getBody());
2021-03-30 09:22:36 +00:00
}
2020-11-25 05:26:25 +00:00
final StreamsPage streamspage = new StreamsPage(nextpage, body, relatedStreams);
2020-11-25 05:26:25 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper.writeValueAsBytes(streamspage);
2020-11-25 05:26:25 +00:00
}
public static final byte[] trendingResponse() throws ParsingException, ExtractionException, IOException {
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
String url = Constants.YOUTUBE_SERVICE.getKioskList().getListLinkHandlerFactoryByType("Trending")
.getUrl("Trending");
KioskInfo info = KioskInfo.getInfo(Constants.YOUTUBE_SERVICE, url);
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
info.getRelatedItems().forEach(o -> {
StreamInfoItem item = o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper.writeValueAsBytes(relatedStreams);
2020-11-12 21:19:45 +00:00
}
public static final byte[] playlistResponse(String playlistId)
2021-02-24 09:52:29 +00:00
throws IOException, ExtractionException, InterruptedException {
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId);
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
info.getRelatedItems().forEach(o -> {
StreamInfoItem item = o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
2021-01-04 05:47:28 +00:00
String nextpage = null, body = null;
2021-03-30 09:36:01 +00:00
if (info.hasNextPage()) {
Page page = info.getNextPage();
nextpage = page.getUrl();
body = Base64.encodeBase64String(info.getNextPage().getBody());
2021-03-30 09:36:01 +00:00
}
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
final Playlist playlist = new Playlist(info.getName(), rewriteURL(info.getThumbnailUrl()),
rewriteURL(info.getBannerUrl()), nextpage, body, info.getUploaderName(),
2021-03-30 09:36:01 +00:00
info.getUploaderUrl().substring(23), rewriteURL(info.getUploaderAvatarUrl()),
(int) info.getStreamCount(), relatedStreams);
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper.writeValueAsBytes(playlist);
2021-01-04 05:47:28 +00:00
}
public static final byte[] playlistPageResponse(String playlistId, String url, String body_req)
2021-02-24 09:52:29 +00:00
throws IOException, ExtractionException, InterruptedException {
2021-01-04 05:47:28 +00:00
2021-03-30 09:36:01 +00:00
InfoItemsPage<StreamInfoItem> info = PlaylistInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
"https://www.youtube.com/playlist?list=" + playlistId, new Page(url, Base64.decodeBase64(body_req)));
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
2021-01-04 05:47:28 +00:00
2021-03-30 09:36:01 +00:00
info.getItems().forEach(o -> {
2021-02-24 09:52:29 +00:00
StreamInfoItem item = o;
relatedStreams.add(new StreamItem(item.getUrl().substring(23), item.getName(),
rewriteURL(item.getThumbnailUrl()), item.getUploaderName(), item.getUploaderUrl().substring(23),
item.getTextualUploadDate(), item.getDuration(), item.getViewCount()));
});
2021-01-04 05:47:28 +00:00
String nextpage = null, body = null;
2021-03-30 09:36:01 +00:00
if (info.hasNextPage()) {
Page page = info.getNextPage();
nextpage = page.getUrl();
body = Base64.encodeBase64String(info.getNextPage().getBody());
2021-03-30 09:36:01 +00:00
}
2021-01-04 05:47:28 +00:00
final StreamsPage streamspage = new StreamsPage(nextpage, body, relatedStreams);
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper.writeValueAsBytes(streamspage);
2021-01-04 05:47:28 +00:00
}
public static final byte[] suggestionsResponse(String query)
2021-02-24 09:52:29 +00:00
throws JsonProcessingException, IOException, ExtractionException {
2020-11-25 05:26:25 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper
.writeValueAsBytes(Constants.YOUTUBE_SERVICE.getSuggestionExtractor().suggestionList(query));
2020-11-25 05:26:25 +00:00
}
public static final byte[] searchResponse(String q) throws IOException, ExtractionException, InterruptedException {
2020-12-09 13:30:42 +00:00
2021-02-24 09:52:29 +00:00
final SearchInfo info = SearchInfo.getInfo(Constants.YOUTUBE_SERVICE,
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q));
ObjectArrayList<SearchItem> items = new ObjectArrayList<>();
info.getRelatedItems().forEach(item -> {
switch (item.getInfoType()) {
case STREAM:
StreamInfoItem stream = (StreamInfoItem) item;
items.add(new SearchStream(item.getName(), rewriteURL(item.getThumbnailUrl()),
2021-05-06 16:26:03 +00:00
item.getUrl().substring(23), stream.getTextualUploadDate(), stream.getUploaderName(),
stream.getUploaderUrl().substring(23), stream.getViewCount(), stream.getDuration()));
2021-02-24 09:52:29 +00:00
break;
case CHANNEL:
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
item.getUrl().substring(23)));
break;
default:
break;
}
});
Page nextpage = info.getNextPage();
return nextpage != null
? Constants.mapper.writeValueAsBytes(new SearchResults(nextpage.getUrl(), nextpage.getId(), items))
: Constants.mapper.writeValueAsBytes(new SearchResults(null, null, items));
2020-12-14 07:11:42 +00:00
}
public static final byte[] searchPageResponse(String q, String url, String id)
2021-02-24 09:52:29 +00:00
throws IOException, ExtractionException, InterruptedException {
InfoItemsPage<InfoItem> pages = SearchInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q), new Page(url, id));
ObjectArrayList<SearchItem> items = new ObjectArrayList<>();
pages.getItems().forEach(item -> {
switch (item.getInfoType()) {
case STREAM:
StreamInfoItem stream = (StreamInfoItem) item;
items.add(new SearchStream(item.getName(), rewriteURL(item.getThumbnailUrl()),
2021-05-06 16:26:03 +00:00
item.getUrl().substring(23), stream.getTextualUploadDate(), stream.getUploaderName(),
stream.getUploaderUrl().substring(23), stream.getViewCount(), stream.getDuration()));
2021-02-24 09:52:29 +00:00
break;
case CHANNEL:
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
item.getUrl().substring(23)));
break;
default:
break;
}
});
Page nextpage = pages.getNextPage();
return nextpage != null
? Constants.mapper.writeValueAsBytes(new SearchResults(nextpage.getUrl(), nextpage.getId(), items))
: Constants.mapper.writeValueAsBytes(new SearchResults(null, null, items));
2020-12-09 13:30:42 +00:00
}
2021-04-03 15:08:32 +00:00
public static final byte[] commentsResponse(String videoId) throws Exception {
CommentsInfo info = commentsCache.get(videoId);
List<Comment> comments = new ObjectArrayList<>();
info.getRelatedItems().forEach(comment -> {
comments.add(new Comment(comment.getUploaderName(), rewriteURL(comment.getUploaderAvatarUrl()),
comment.getCommentId(), comment.getCommentText(), comment.getTextualUploadDate(),
2021-05-03 15:36:53 +00:00
comment.getUploaderUrl().substring(19), comment.getLikeCount(), comment.isHeartedByUploader(),
2021-04-03 15:08:32 +00:00
comment.isPinned(), comment.isUploaderVerified()));
});
String nextpage = null;
if (info.getNextPage() != null)
nextpage = info.getNextPage().getUrl();
CommentsPage commentsItem = new CommentsPage(comments, nextpage);
return Constants.mapper.writeValueAsBytes(commentsItem);
}
public static final byte[] commentsPageResponse(String videoId, String url) throws Exception {
CommentsInfo init = commentsCache.get(videoId);
InfoItemsPage<CommentsInfoItem> info = CommentsInfo.getMoreItems(init, new Page(url));
List<Comment> comments = new ObjectArrayList<>();
info.getItems().forEach(comment -> {
comments.add(new Comment(comment.getUploaderName(), rewriteURL(comment.getUploaderAvatarUrl()),
comment.getCommentId(), comment.getCommentText(), comment.getTextualUploadDate(),
2021-05-03 15:36:53 +00:00
comment.getUploaderUrl().substring(19), comment.getLikeCount(), comment.isHeartedByUploader(),
2021-04-03 15:08:32 +00:00
comment.isPinned(), comment.isUploaderVerified()));
});
String nextpage = null;
if (info.getNextPage() != null)
nextpage = info.getNextPage().getUrl();
CommentsPage commentsItem = new CommentsPage(comments, nextpage);
return Constants.mapper.writeValueAsBytes(commentsItem);
}
public static final byte[] registerResponse(String user, String pass) throws IOException {
2021-01-04 05:47:28 +00:00
2021-02-24 09:52:29 +00:00
return Constants.mapper.writeValueAsBytes(null);
2021-01-04 05:47:28 +00:00
}
2020-11-12 21:19:45 +00:00
private static final String getLBRYStreamURL(String videoId) throws IOException, InterruptedException {
2021-02-24 09:52:29 +00:00
String lbryId = new JSONObject(Constants.h2client.send(HttpRequest
.newBuilder(URI.create("https://api.lbry.com/yt/resolve?video_ids=" + URLUtils.silentEncode(videoId)))
.setHeader("User-Agent", Constants.USER_AGENT).build(), BodyHandlers.ofString()).body())
.getJSONObject("data").getJSONObject("videos").optString(videoId);
if (!lbryId.isEmpty())
2021-04-03 15:08:32 +00:00
new JSONObject(Constants.h2client.send(HttpRequest
.newBuilder(URI.create("https://api.lbry.tv/api/v1/proxy?m=get"))
.POST(BodyPublishers.ofString(
String.valueOf(new JSONObject().put("jsonrpc", "2.0").put("method", "get").put("params",
new JSONObject().put("uri", "lbry://" + lbryId).put("save_file", true)))))
.build(), BodyHandlers.ofString()).body()).getJSONObject("result").getString("streaming_url");
2021-02-24 09:52:29 +00:00
return null;
2020-11-12 21:19:45 +00:00
}
private static String rewriteURL(final String old) {
2021-02-24 09:52:29 +00:00
if (Constants.debug)
return old;
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
if (old == null || old.isEmpty())
return null;
2020-12-09 13:29:12 +00:00
2021-02-24 09:52:29 +00:00
URL url = null;
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
try {
url = new URL(old);
} catch (MalformedURLException e) {
e.printStackTrace();
}
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
final String host = url.getHost();
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
String query = url.getQuery();
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
boolean hasQuery = query != null;
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
String path = url.getPath();
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
path = path.replace("-rj", "-rw");
2020-11-12 21:19:45 +00:00
2021-02-24 09:52:29 +00:00
return Constants.PROXY_PART + path + (hasQuery ? "?" + query + "&host=" : "?host=")
+ URLUtils.silentEncode(host);
2020-11-12 21:19:45 +00:00
}
}