mirror of
https://github.com/TeamPiped/Piped-Backend
synced 2025-09-04 04:21:20 +02:00
Commit changes.
This commit is contained in:
parent
947d6d5787
commit
dd2ee203bb
@ -19,7 +19,7 @@ dependencies {
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
|
||||
implementation 'org.mongodb:mongodb-driver-sync:4.2.1'
|
||||
implementation 'io.projectreactor.netty:reactor-netty:1.0.4'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.20.8'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:SNAPSHOT'
|
||||
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.1'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.12.1'
|
||||
@ -27,6 +27,8 @@ dependencies {
|
||||
implementation 'org.json:json:20201115'
|
||||
implementation 'com.github.ben-manes.caffeine:caffeine:2.8.6'
|
||||
implementation 'com.rometools:rome:1.15.0'
|
||||
implementation 'com.github.ipfs:java-ipfs-http-client:v1.3.3'
|
||||
implementation 'net.java.dev.jna:jna-platform:5.7.0'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
@ -1,6 +1,13 @@
|
||||
package me.kavin.piped;
|
||||
|
||||
import io.netty.util.AsciiString;
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN;
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.CACHE_CONTROL;
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
|
||||
import static io.netty.handler.codec.http.HttpHeaderValues.APPLICATION_JSON;
|
||||
import static io.netty.handler.codec.http.HttpHeaderValues.TEXT_PLAIN;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.localization.Localization;
|
||||
@ -11,6 +18,7 @@ import com.rometools.rome.io.XmlReader;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
import io.netty.util.AsciiString;
|
||||
import me.kavin.piped.consts.Constants;
|
||||
import me.kavin.piped.utils.DownloaderImpl;
|
||||
import me.kavin.piped.utils.ResponseHelper;
|
||||
@ -22,231 +30,233 @@ import reactor.netty.NettyOutbound;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
import reactor.netty.http.server.HttpServerResponse;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.*;
|
||||
import static io.netty.handler.codec.http.HttpHeaderValues.*;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
NewPipe.init(new DownloaderImpl(), new Localization("en", "US"));
|
||||
NewPipe.init(new DownloaderImpl(), new Localization("en", "US"));
|
||||
|
||||
DisposableServer server = HttpServer.create().port(Constants.PORT).route(routes -> {
|
||||
|
||||
routes.get("/webhooks/pubsub", (req, res) -> {
|
||||
routes.get("/webhooks/pubsub", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res, query.parameters().get("hub.challenge").get(0), TEXT_PLAIN, 200, "private", start);
|
||||
try {
|
||||
return writeResponse(res, query.parameters().get("hub.challenge").get(0), TEXT_PLAIN, 200,
|
||||
"private", start);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.post("/webhooks/pubsub", (req, res) -> {
|
||||
routes.post("/webhooks/pubsub", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
long start = System.nanoTime();
|
||||
|
||||
try {
|
||||
req.receive().asInputStream().subscribe(in -> {
|
||||
try {
|
||||
SyndFeed feed = new SyndFeedInput().build(new XmlReader(in));
|
||||
try {
|
||||
req.receive().asInputStream().subscribe(in -> {
|
||||
try {
|
||||
SyndFeed feed = new SyndFeedInput().build(new XmlReader(in));
|
||||
|
||||
feed.getEntries().forEach(entry -> {
|
||||
System.out.println(entry.getLinks().get(0).getHref());
|
||||
System.out.println(entry.getAuthors().get(0).getUri());
|
||||
});
|
||||
feed.getEntries().forEach(entry -> {
|
||||
System.out.println(entry.getLinks().get(0).getHref());
|
||||
System.out.println(entry.getAuthors().get(0).getUri());
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return writeResponse(res, "ok", TEXT_PLAIN, 200, "private", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return writeResponse(res, "ok", TEXT_PLAIN, 200, "private", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/sponsors/{videoId}", (req, res) -> {
|
||||
routes.get("/sponsors/{videoId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res, SponsorBlockUtils.getSponsors(req.param("videoId"),
|
||||
query.parameters().get("category").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res, SponsorBlockUtils.getSponsors(req.param("videoId"),
|
||||
query.parameters().get("category").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/streams/{videoId}", (req, res) -> {
|
||||
routes.get("/streams/{videoId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
// The stream links are valid for 6 hours.
|
||||
return writeResponse(res, ResponseHelper.streamsResponse(req.param("videoId")), 200,
|
||||
"public, s-maxage=21540", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
// The stream links are valid for 6 hours.
|
||||
return writeResponse(res, ResponseHelper.streamsResponse(req.param("videoId")), 200,
|
||||
"public, s-maxage=21540", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/channels/{channelId}", (req, res) -> {
|
||||
routes.get("/channels/{channelId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.channelResponse(req.param("channelId")), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.channelResponse(req.param("channelId")), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/nextpage/channels/{channelId}", (req, res) -> {
|
||||
routes.get("/nextpage/channels/{channelId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.channelPageResponse(req.param("channelId"),
|
||||
query.parameters().get("url").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.channelPageResponse(req.param("channelId"),
|
||||
query.parameters().get("url").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/playlists/{playlistId}", (req, res) -> {
|
||||
routes.get("/playlists/{playlistId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.playlistResponse(req.param("playlistId")), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.playlistResponse(req.param("playlistId")), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/nextpage/playlists/{playlistId}", (req, res) -> {
|
||||
routes.get("/nextpage/playlists/{playlistId}", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.playlistPageResponse(req.param("playlistId"),
|
||||
query.parameters().get("url").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.playlistPageResponse(req.param("playlistId"),
|
||||
query.parameters().get("url").get(0)), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/suggestions", (req, res) -> {
|
||||
routes.get("/suggestions", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res,
|
||||
ResponseHelper.suggestionsResponse(query.parameters().get("query").get(0)), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res,
|
||||
ResponseHelper.suggestionsResponse(query.parameters().get("query").get(0)), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/search", (req, res) -> {
|
||||
routes.get("/search", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.searchResponse(query.parameters().get("q").get(0)), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.searchResponse(query.parameters().get("q").get(0)), 200,
|
||||
"public, max-age=600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/nextpage/search", (req, res) -> {
|
||||
routes.get("/nextpage/search", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
long start = System.nanoTime();
|
||||
QueryStringDecoder query = new QueryStringDecoder(req.uri());
|
||||
|
||||
try {
|
||||
return writeResponse(res,
|
||||
ResponseHelper.searchPageResponse(query.parameters().get("q").get(0),
|
||||
query.parameters().get("url").get(0), query.parameters().get("id").get(0)),
|
||||
200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
try {
|
||||
return writeResponse(res,
|
||||
ResponseHelper.searchPageResponse(query.parameters().get("q").get(0),
|
||||
query.parameters().get("url").get(0), query.parameters().get("id").get(0)),
|
||||
200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
routes.get("/trending", (req, res) -> {
|
||||
routes.get("/trending", (req, res) -> {
|
||||
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.trendingResponse(), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return writeResponse(res, ResponseHelper.trendingResponse(), 200, "public, max-age=3600", start);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return writeResponse(res, ExceptionUtils.getStackTrace(e), 500, "private", start);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
}).compress(true).bindNow();
|
||||
|
||||
server.onDispose().block();
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache, time);
|
||||
}
|
||||
}).bindNow();
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, AsciiString mimeType, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, String mimeType, int code, String cache, long time) {
|
||||
return writeResponse(res, resp.getBytes(StandardCharsets.UTF_8), mimeType, code, cache, time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, byte[] resp, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache, time);
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, byte[] resp, AsciiString mimeType, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache, time);
|
||||
}
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, AsciiString mimeType, int code,
|
||||
String cache, long time) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, String resp, String mimeType, int code,
|
||||
String cache, long time) {
|
||||
return writeResponse(res, resp.getBytes(StandardCharsets.UTF_8), mimeType, code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, byte[] resp, int code, String cache, long time) {
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, byte[] resp, AsciiString mimeType, int code,
|
||||
String cache, long time) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache, time);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, byte[] resp, String mimeType, int code, String cache, long time) {
|
||||
return res
|
||||
@ -258,15 +268,14 @@ public class Main {
|
||||
.sendByteArray(Flux.just(resp));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, Flux<String> resp, int code, String cache) {
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache);
|
||||
return writeResponse(res, resp, APPLICATION_JSON, code, cache);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, Flux<String> resp, AsciiString mimeType, int code, String cache) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache);
|
||||
}
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, Flux<String> resp, AsciiString mimeType, int code,
|
||||
String cache) {
|
||||
return writeResponse(res, resp, mimeType.toString(), code, cache);
|
||||
}
|
||||
|
||||
public static NettyOutbound writeResponse(HttpServerResponse res, Flux<String> resp, String mimeType, int code, String cache) {
|
||||
return res
|
||||
|
@ -10,6 +10,8 @@ import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
|
||||
public class Constants {
|
||||
|
||||
@ -24,21 +26,24 @@ public class Constants {
|
||||
public static final StreamingService YOUTUBE_SERVICE;
|
||||
|
||||
public static final HttpClient h2client = HttpClient.newBuilder().followRedirects(Redirect.NORMAL)
|
||||
.version(Version.HTTP_2).build();
|
||||
.version(Version.HTTP_2).build();
|
||||
// public static final HttpClient h3client = Http3ClientBuilder.newBuilder().followRedirects(Redirect.NORMAL).build();
|
||||
|
||||
public static final MongoClient mongoClient;
|
||||
|
||||
public static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
YOUTUBE_SERVICE = NewPipe.getService(0);
|
||||
prop.load(new FileReader("config.properties"));
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
YOUTUBE_SERVICE = NewPipe.getService(0);
|
||||
prop.load(new FileReader("config.properties"));
|
||||
|
||||
PORT = Integer.parseInt(prop.getProperty("PORT"));
|
||||
PROXY_PART = prop.getProperty("PROXY_PART");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
PORT = Integer.parseInt(prop.getProperty("PORT"));
|
||||
PROXY_PART = prop.getProperty("PROXY_PART");
|
||||
mongoClient = MongoClients.create(prop.getProperty("MONGO_URI"));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
20
src/main/java/me/kavin/piped/ipfs/IPFS.java
Normal file
20
src/main/java/me/kavin/piped/ipfs/IPFS.java
Normal file
@ -0,0 +1,20 @@
|
||||
package me.kavin.piped.ipfs;
|
||||
|
||||
import me.kavin.piped.utils.Multithreading;
|
||||
import me.kavin.piped.utils.obj.Channel;
|
||||
|
||||
public class IPFS {
|
||||
|
||||
// private static final io.ipfs.api.IPFS ipfs = new io.ipfs.api.IPFS(new MultiAddress("/ip4/127.0.0.1/tcp/5001"));
|
||||
|
||||
public static void publishData(final Channel channel) {
|
||||
Multithreading.runAsync(() -> {
|
||||
try {
|
||||
// ipfs.pubsub.pub(URLUtils.silentEncode(channel.id),
|
||||
// URLUtils.silentEncode(Constants.mapper.writeValueAsString(channel)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -9,13 +9,13 @@ public class CookieHandler extends java.net.CookieHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,32 +23,32 @@ public class DownloaderImpl extends Downloader {
|
||||
@Override
|
||||
public Response execute(Request request) throws IOException, ReCaptchaException {
|
||||
|
||||
// TODO: HTTP/3 aka QUIC
|
||||
Builder builder = HttpRequest.newBuilder(URI.create(request.url()));
|
||||
// TODO: HTTP/3 aka QUIC
|
||||
Builder builder = HttpRequest.newBuilder(URI.create(request.url()));
|
||||
|
||||
byte[] data = request.dataToSend();
|
||||
BodyPublisher publisher = data == null ? HttpRequest.BodyPublishers.noBody()
|
||||
: HttpRequest.BodyPublishers.ofByteArray(data);
|
||||
byte[] data = request.dataToSend();
|
||||
BodyPublisher publisher = data == null ? HttpRequest.BodyPublishers.noBody()
|
||||
: HttpRequest.BodyPublishers.ofByteArray(data);
|
||||
|
||||
builder.method(request.httpMethod(), publisher);
|
||||
request.headers().forEach((name, values) -> values.forEach(value -> builder.header(name, value)));
|
||||
builder.method(request.httpMethod(), publisher);
|
||||
request.headers().forEach((name, values) -> values.forEach(value -> builder.header(name, value)));
|
||||
|
||||
builder.setHeader("User-Agent", Constants.USER_AGENT);
|
||||
builder.setHeader("User-Agent", Constants.USER_AGENT);
|
||||
|
||||
HttpResponse<String> response = null;
|
||||
HttpResponse<String> response = null;
|
||||
|
||||
try {
|
||||
response = Constants.h2client.send(builder.build(), BodyHandlers.ofString());
|
||||
} catch (InterruptedException e) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
response = Constants.h2client.send(builder.build(), BodyHandlers.ofString());
|
||||
} catch (InterruptedException e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
// TODO: Implement solver
|
||||
if (response.statusCode() == 429) {
|
||||
throw new ReCaptchaException("reCaptcha Challenge requested", String.valueOf(response.uri()));
|
||||
}
|
||||
// TODO: Implement solver
|
||||
if (response.statusCode() == 429) {
|
||||
throw new ReCaptchaException("reCaptcha Challenge requested", String.valueOf(response.uri()));
|
||||
}
|
||||
|
||||
return new Response(response.statusCode(), "UNDEFINED", response.headers().map(), response.body(),
|
||||
String.valueOf(response.uri()));
|
||||
return new Response(response.statusCode(), "UNDEFINED", response.headers().map(), response.body(),
|
||||
String.valueOf(response.uri()));
|
||||
}
|
||||
}
|
||||
|
19
src/main/java/me/kavin/piped/utils/Multithreading.java
Normal file
19
src/main/java/me/kavin/piped/utils/Multithreading.java
Normal file
@ -0,0 +1,19 @@
|
||||
package me.kavin.piped.utils;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Multithreading {
|
||||
|
||||
private static final ExecutorService es = Executors.newFixedThreadPool(16);
|
||||
|
||||
public static void runAsync(final Runnable runnable) {
|
||||
es.submit(runnable);
|
||||
}
|
||||
|
||||
public static void runAsyncTimeout(final Runnable runnable) {
|
||||
|
||||
es.submit(runnable);
|
||||
|
||||
}
|
||||
}
|
7
src/main/java/me/kavin/piped/utils/RegisterRequest.java
Normal file
7
src/main/java/me/kavin/piped/utils/RegisterRequest.java
Normal file
@ -0,0 +1,7 @@
|
||||
package me.kavin.piped.utils;
|
||||
|
||||
public class RegisterRequest {
|
||||
|
||||
public String username, password;
|
||||
|
||||
}
|
@ -10,7 +10,6 @@ import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
@ -34,7 +33,9 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import me.kavin.piped.consts.Constants;
|
||||
import me.kavin.piped.ipfs.IPFS;
|
||||
import me.kavin.piped.utils.obj.Channel;
|
||||
import me.kavin.piped.utils.obj.ChapterSegment;
|
||||
import me.kavin.piped.utils.obj.PipedStream;
|
||||
import me.kavin.piped.utils.obj.Playlist;
|
||||
import me.kavin.piped.utils.obj.SearchResults;
|
||||
@ -48,353 +49,361 @@ import me.kavin.piped.utils.obj.search.SearchStream;
|
||||
public class ResponseHelper {
|
||||
|
||||
public static final LoadingCache<String, CommentsInfo> commentsCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.HOURS).maximumSize(1000)
|
||||
.build(key -> CommentsInfo.getInfo("https://www.youtube.com/watch?v=" + key));
|
||||
.expireAfterWrite(1, TimeUnit.HOURS).maximumSize(1000)
|
||||
.build(key -> CommentsInfo.getInfo("https://www.youtube.com/watch?v=" + key));
|
||||
|
||||
public static final byte[] streamsResponse(String videoId) throws Exception {
|
||||
|
||||
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<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;
|
||||
});
|
||||
CompletableFuture<String> futureLBRY = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return getLBRYStreamURL(videoId);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.rethrow(e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
final List<Subtitle> subtitles = new ObjectArrayList<>();
|
||||
final List<Subtitle> subtitles = new ObjectArrayList<>();
|
||||
|
||||
final StreamInfo info = futureStream.get();
|
||||
final StreamInfo info = futureStream.get();
|
||||
|
||||
info.getSubtitles().forEach(subtitle -> subtitles
|
||||
.add(new Subtitle(rewriteURL(subtitle.getUrl()), subtitle.getFormat().getMimeType())));
|
||||
// System.out.println(Constants.mapper.writeValueAsString(info.getStreamSegments()));
|
||||
info.getSubtitles().forEach(subtitle -> subtitles
|
||||
.add(new Subtitle(rewriteURL(subtitle.getUrl()), subtitle.getFormat().getMimeType())));
|
||||
|
||||
final List<PipedStream> videoStreams = new ObjectArrayList<>();
|
||||
final List<PipedStream> audioStreams = new ObjectArrayList<>();
|
||||
final List<PipedStream> videoStreams = new ObjectArrayList<>();
|
||||
final List<PipedStream> audioStreams = new ObjectArrayList<>();
|
||||
|
||||
final String lbryURL = futureLBRY.get();
|
||||
final String lbryURL = futureLBRY.get();
|
||||
|
||||
if (lbryURL != null)
|
||||
videoStreams.add(new PipedStream(lbryURL, "MP4", "LBRY", "video/mp4", false));
|
||||
if (lbryURL != null)
|
||||
videoStreams.add(new PipedStream(lbryURL, "MP4", "LBRY", "video/mp4", false));
|
||||
|
||||
final String hls;
|
||||
boolean livestream = false;
|
||||
final String hls;
|
||||
boolean livestream = false;
|
||||
|
||||
if ((hls = info.getHlsUrl()) != null && !hls.isEmpty())
|
||||
livestream = true;
|
||||
if ((hls = info.getHlsUrl()) != null && !hls.isEmpty())
|
||||
livestream = true;
|
||||
|
||||
if (hls != null) {
|
||||
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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
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)));
|
||||
info.getVideoStreams()
|
||||
.forEach(stream -> videoStreams
|
||||
.add(new PipedStream(rewriteURL(stream.getUrl()), String.valueOf(stream.getFormat()),
|
||||
stream.getResolution(), stream.getFormat().getMimeType(), 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)));
|
||||
}
|
||||
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<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
info.getRelatedStreams().forEach(o -> {
|
||||
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()));
|
||||
});
|
||||
info.getRelatedStreams().forEach(o -> {
|
||||
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()));
|
||||
});
|
||||
|
||||
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);
|
||||
List<ChapterSegment> segments = new ObjectArrayList<>();
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(streams);
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] channelResponse(String channelId)
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
public static final byte[] channelResponse(String channelId) throws Exception {
|
||||
|
||||
final ChannelInfo info = ChannelInfo.getInfo("https://youtube.com/channel/" + channelId);
|
||||
final ChannelInfo info = ChannelInfo.getInfo("https://youtube.com/channel/" + channelId);
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
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()));
|
||||
});
|
||||
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()));
|
||||
});
|
||||
|
||||
String nextpage = info.hasNextPage() ? info.getNextPage().getUrl() : null;
|
||||
String nextpage = info.hasNextPage() ? info.getNextPage().getUrl() : null;
|
||||
|
||||
final Channel channel = new Channel(info.getName(), rewriteURL(info.getAvatarUrl()),
|
||||
rewriteURL(info.getBannerUrl()), info.getDescription(), nextpage, relatedStreams);
|
||||
final Channel channel = new Channel(info.getId(), info.getName(), rewriteURL(info.getAvatarUrl()),
|
||||
rewriteURL(info.getBannerUrl()), info.getDescription(), nextpage, relatedStreams);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(channel);
|
||||
IPFS.publishData(channel);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(channel);
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] channelPageResponse(String channelId, String url)
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
|
||||
InfoItemsPage<StreamInfoItem> page = ChannelInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
"https://youtube.com/channel/" + channelId, new Page(url));
|
||||
InfoItemsPage<StreamInfoItem> page = ChannelInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
"https://youtube.com/channel/" + channelId, new Page(url));
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
page.getItems().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()));
|
||||
});
|
||||
page.getItems().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()));
|
||||
});
|
||||
|
||||
String nextpage = page.hasNextPage() ? page.getNextPage().getUrl() : null;
|
||||
String nextpage = page.hasNextPage() ? page.getNextPage().getUrl() : null;
|
||||
|
||||
final StreamsPage streamspage = new StreamsPage(nextpage, relatedStreams);
|
||||
final StreamsPage streamspage = new StreamsPage(nextpage, relatedStreams);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(streamspage);
|
||||
return Constants.mapper.writeValueAsBytes(streamspage);
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] trendingResponse() throws ParsingException, ExtractionException, IOException {
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
String url = Constants.YOUTUBE_SERVICE.getKioskList().getListLinkHandlerFactoryByType("Trending")
|
||||
.getUrl("Trending");
|
||||
KioskInfo info = KioskInfo.getInfo(Constants.YOUTUBE_SERVICE, url);
|
||||
String url = Constants.YOUTUBE_SERVICE.getKioskList().getListLinkHandlerFactoryByType("Trending")
|
||||
.getUrl("Trending");
|
||||
KioskInfo info = KioskInfo.getInfo(Constants.YOUTUBE_SERVICE, url);
|
||||
|
||||
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()));
|
||||
});
|
||||
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()));
|
||||
});
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(relatedStreams);
|
||||
return Constants.mapper.writeValueAsBytes(relatedStreams);
|
||||
}
|
||||
|
||||
public static final byte[] playlistResponse(String playlistId)
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
|
||||
final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId);
|
||||
final PlaylistInfo info = PlaylistInfo.getInfo("https://www.youtube.com/playlist?list=" + playlistId);
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
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()));
|
||||
});
|
||||
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()));
|
||||
});
|
||||
|
||||
String nextpage = info.hasNextPage() ? info.getNextPage().getUrl() : null;
|
||||
String nextpage = info.hasNextPage() ? info.getNextPage().getUrl() : null;
|
||||
|
||||
final Playlist playlist = new Playlist(info.getName(), rewriteURL(info.getThumbnailUrl()),
|
||||
rewriteURL(info.getBannerUrl()), nextpage, info.getUploaderName(), info.getUploaderUrl().substring(23),
|
||||
rewriteURL(info.getUploaderAvatarUrl()), (int) info.getStreamCount(), relatedStreams);
|
||||
final Playlist playlist = new Playlist(info.getName(), rewriteURL(info.getThumbnailUrl()),
|
||||
rewriteURL(info.getBannerUrl()), nextpage, info.getUploaderName(), info.getUploaderUrl().substring(23),
|
||||
rewriteURL(info.getUploaderAvatarUrl()), (int) info.getStreamCount(), relatedStreams);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(playlist);
|
||||
return Constants.mapper.writeValueAsBytes(playlist);
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] playlistPageResponse(String playlistId, String url)
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
|
||||
InfoItemsPage<StreamInfoItem> page = PlaylistInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
"https://www.youtube.com/playlist?list=" + playlistId, new Page(url));
|
||||
InfoItemsPage<StreamInfoItem> page = PlaylistInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
"https://www.youtube.com/playlist?list=" + playlistId, new Page(url));
|
||||
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
final List<StreamItem> relatedStreams = new ObjectArrayList<>();
|
||||
|
||||
page.getItems().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()));
|
||||
});
|
||||
page.getItems().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()));
|
||||
});
|
||||
|
||||
String nextpage = page.hasNextPage() ? page.getNextPage().getUrl() : null;
|
||||
String nextpage = page.hasNextPage() ? page.getNextPage().getUrl() : null;
|
||||
|
||||
final StreamsPage streamspage = new StreamsPage(nextpage, relatedStreams);
|
||||
final StreamsPage streamspage = new StreamsPage(nextpage, relatedStreams);
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(streamspage);
|
||||
return Constants.mapper.writeValueAsBytes(streamspage);
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] suggestionsResponse(String query)
|
||||
throws JsonProcessingException, IOException, ExtractionException {
|
||||
throws JsonProcessingException, IOException, ExtractionException {
|
||||
|
||||
return Constants.mapper
|
||||
.writeValueAsBytes(Constants.YOUTUBE_SERVICE.getSuggestionExtractor().suggestionList(query));
|
||||
return Constants.mapper
|
||||
.writeValueAsBytes(Constants.YOUTUBE_SERVICE.getSuggestionExtractor().suggestionList(query));
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] searchResponse(String q) throws IOException, ExtractionException, InterruptedException {
|
||||
|
||||
final SearchInfo info = SearchInfo.getInfo(Constants.YOUTUBE_SERVICE,
|
||||
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q));
|
||||
final SearchInfo info = SearchInfo.getInfo(Constants.YOUTUBE_SERVICE,
|
||||
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q));
|
||||
|
||||
ObjectArrayList<SearchItem> items = new ObjectArrayList<>();
|
||||
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()),
|
||||
item.getUrl().substring(23), stream.getViewCount(), stream.getDuration()));
|
||||
break;
|
||||
case CHANNEL:
|
||||
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
info.getRelatedItems().forEach(item -> {
|
||||
switch (item.getInfoType()) {
|
||||
case STREAM:
|
||||
StreamInfoItem stream = (StreamInfoItem) item;
|
||||
items.add(new SearchStream(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23), stream.getViewCount(), stream.getDuration()));
|
||||
break;
|
||||
case CHANNEL:
|
||||
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
Page nextpage = info.getNextPage();
|
||||
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));
|
||||
return nextpage != null
|
||||
? Constants.mapper.writeValueAsBytes(new SearchResults(nextpage.getUrl(), nextpage.getId(), items))
|
||||
: Constants.mapper.writeValueAsBytes(new SearchResults(null, null, items));
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] searchPageResponse(String q, String url, String id)
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
throws IOException, ExtractionException, InterruptedException {
|
||||
|
||||
InfoItemsPage<InfoItem> pages = SearchInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q), new Page(url, id));
|
||||
InfoItemsPage<InfoItem> pages = SearchInfo.getMoreItems(Constants.YOUTUBE_SERVICE,
|
||||
Constants.YOUTUBE_SERVICE.getSearchQHFactory().fromQuery(q), new Page(url, id));
|
||||
|
||||
ObjectArrayList<SearchItem> items = new ObjectArrayList<>();
|
||||
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()),
|
||||
item.getUrl().substring(23), stream.getViewCount(), stream.getDuration()));
|
||||
break;
|
||||
case CHANNEL:
|
||||
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
pages.getItems().forEach(item -> {
|
||||
switch (item.getInfoType()) {
|
||||
case STREAM:
|
||||
StreamInfoItem stream = (StreamInfoItem) item;
|
||||
items.add(new SearchStream(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23), stream.getViewCount(), stream.getDuration()));
|
||||
break;
|
||||
case CHANNEL:
|
||||
items.add(new SearchItem(item.getName(), rewriteURL(item.getThumbnailUrl()),
|
||||
item.getUrl().substring(23)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
Page nextpage = pages.getNextPage();
|
||||
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));
|
||||
return nextpage != null
|
||||
? Constants.mapper.writeValueAsBytes(new SearchResults(nextpage.getUrl(), nextpage.getId(), items))
|
||||
: Constants.mapper.writeValueAsBytes(new SearchResults(null, null, items));
|
||||
|
||||
}
|
||||
|
||||
public static final byte[] registerResponse(String user, String pass) throws IOException {
|
||||
|
||||
return Constants.mapper.writeValueAsBytes(null);
|
||||
return Constants.mapper.writeValueAsBytes(null);
|
||||
|
||||
}
|
||||
|
||||
private static final String getLBRYStreamURL(String videoId) throws IOException, InterruptedException {
|
||||
|
||||
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);
|
||||
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())
|
||||
return rewriteURL(
|
||||
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"));
|
||||
if (!lbryId.isEmpty())
|
||||
return rewriteURL(
|
||||
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"));
|
||||
|
||||
return null;
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
private static String rewriteURL(final String old) {
|
||||
|
||||
if (Constants.debug)
|
||||
return old;
|
||||
if (Constants.debug)
|
||||
return old;
|
||||
|
||||
if (old == null || old.isEmpty())
|
||||
return null;
|
||||
if (old == null || old.isEmpty())
|
||||
return null;
|
||||
|
||||
URL url = null;
|
||||
URL url = null;
|
||||
|
||||
try {
|
||||
url = new URL(old);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
url = new URL(old);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final String host = url.getHost();
|
||||
final String host = url.getHost();
|
||||
|
||||
String query = url.getQuery();
|
||||
String query = url.getQuery();
|
||||
|
||||
boolean hasQuery = query != null;
|
||||
boolean hasQuery = query != null;
|
||||
|
||||
String path = url.getPath();
|
||||
String path = url.getPath();
|
||||
|
||||
path = path.replace("-rj", "-rw");
|
||||
path = path.replace("-rj", "-rw");
|
||||
|
||||
if (path.startsWith("/vi/") && !path.contains("_live")) {
|
||||
path = path.replace("/vi/", "/vi_webp/").replace(".jpg", ".webp").replace("hq720", "mqdefault")
|
||||
.replace("hqdefault", "mqdefault");
|
||||
if (path.startsWith("/vi/") && !path.contains("_live")) {
|
||||
path = path.replace("/vi/", "/vi_webp/").replace(".jpg", ".webp").replace("hq720", "mqdefault")
|
||||
.replace("hqdefault", "mqdefault");
|
||||
|
||||
hasQuery = false;
|
||||
}
|
||||
hasQuery = false;
|
||||
}
|
||||
|
||||
return Constants.PROXY_PART + path + (hasQuery ? "?" + query + "&host=" : "?host=")
|
||||
+ URLUtils.silentEncode(host);
|
||||
return Constants.PROXY_PART + path + (hasQuery ? "?" + query + "&host=" : "?host=")
|
||||
+ URLUtils.silentEncode(host);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -19,36 +19,36 @@ import me.kavin.piped.consts.Constants;
|
||||
public class SponsorBlockUtils {
|
||||
|
||||
public static final String getSponsors(String id, String categories)
|
||||
throws IOException, InterruptedException, NoSuchAlgorithmException, JsonParserException {
|
||||
throws IOException, InterruptedException, NoSuchAlgorithmException, JsonParserException {
|
||||
|
||||
String hash = toSha256(id);
|
||||
String hash = toSha256(id);
|
||||
|
||||
URI uri = URI.create("https://sponsor.ajay.app/api/skipSegments/" + URLUtils.silentEncode(hash.substring(0, 4))
|
||||
+ "?categories=" + URLUtils.silentEncode(categories));
|
||||
URI uri = URI.create("https://sponsor.ajay.app/api/skipSegments/" + URLUtils.silentEncode(hash.substring(0, 4))
|
||||
+ "?categories=" + URLUtils.silentEncode(categories));
|
||||
|
||||
JsonArray jArray = JsonParser.array()
|
||||
.from(Constants.h2client.send(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()).body());
|
||||
JsonArray jArray = JsonParser.array()
|
||||
.from(Constants.h2client.send(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()).body());
|
||||
|
||||
jArray.removeIf(jObject -> !((JsonObject) jObject).getString("videoID").equalsIgnoreCase(id));
|
||||
jArray.removeIf(jObject -> !((JsonObject) jObject).getString("videoID").equalsIgnoreCase(id));
|
||||
|
||||
return JsonWriter.string(jArray.getObject(0));
|
||||
return JsonWriter.string(jArray.getObject(0));
|
||||
}
|
||||
|
||||
private static final String toSha256(final String videoId) throws NoSuchAlgorithmException {
|
||||
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
final byte[] bytes = digest.digest(videoId.getBytes(StandardCharsets.UTF_8));
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
final byte[] bytes = digest.digest(videoId.getBytes(StandardCharsets.UTF_8));
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (final byte b : bytes) {
|
||||
final String hex = Integer.toHexString(0xff & b);
|
||||
for (final byte b : bytes) {
|
||||
final String hex = Integer.toHexString(0xff & b);
|
||||
|
||||
if (hex.length() == 1) {
|
||||
sb.append('0');
|
||||
}
|
||||
if (hex.length() == 1) {
|
||||
sb.append('0');
|
||||
}
|
||||
|
||||
sb.append(hex);
|
||||
}
|
||||
sb.append(hex);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import java.net.URLEncoder;
|
||||
public class URLUtils {
|
||||
|
||||
public static String silentEncode(String s) {
|
||||
try {
|
||||
return URLEncoder.encode(s, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
// ignored
|
||||
}
|
||||
return s;
|
||||
try {
|
||||
return URLEncoder.encode(s, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
// ignored
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,17 @@ import java.util.List;
|
||||
|
||||
public class Channel {
|
||||
|
||||
public String name, avatarUrl, bannerUrl, description, nextpage;
|
||||
public String id, name, avatarUrl, bannerUrl, description, nextpage;
|
||||
public List<StreamItem> relatedStreams;
|
||||
|
||||
public Channel(String name, String avatarUrl, String bannerUrl, String description, String nextpage,
|
||||
List<StreamItem> relatedStreams) {
|
||||
this.name = name;
|
||||
this.avatarUrl = avatarUrl;
|
||||
this.bannerUrl = bannerUrl;
|
||||
this.description = description;
|
||||
this.nextpage = nextpage;
|
||||
this.relatedStreams = relatedStreams;
|
||||
public Channel(String id, String name, String avatarUrl, String bannerUrl, String description, String nextpage,
|
||||
List<StreamItem> relatedStreams) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.avatarUrl = avatarUrl;
|
||||
this.bannerUrl = bannerUrl;
|
||||
this.description = description;
|
||||
this.nextpage = nextpage;
|
||||
this.relatedStreams = relatedStreams;
|
||||
}
|
||||
}
|
||||
|
12
src/main/java/me/kavin/piped/utils/obj/ChapterSegment.java
Normal file
12
src/main/java/me/kavin/piped/utils/obj/ChapterSegment.java
Normal file
@ -0,0 +1,12 @@
|
||||
package me.kavin.piped.utils.obj;
|
||||
|
||||
public class ChapterSegment {
|
||||
|
||||
public String title;
|
||||
public int start;
|
||||
|
||||
public ChapterSegment(String title, int start) {
|
||||
this.title = title;
|
||||
this.start = start;
|
||||
}
|
||||
}
|
@ -2,14 +2,49 @@ package me.kavin.piped.utils.obj;
|
||||
|
||||
public class PipedStream {
|
||||
|
||||
public String url, format, quality, mimeType;
|
||||
public String url, format, quality, mimeType, codec;
|
||||
public boolean videoOnly;
|
||||
|
||||
public int bitrate, initStart, initEnd, indexStart, indexEnd, width, height, fps;
|
||||
|
||||
public PipedStream(String url, String format, String quality, String mimeType, boolean videoOnly) {
|
||||
this.url = url;
|
||||
this.format = format;
|
||||
this.quality = quality;
|
||||
this.mimeType = mimeType;
|
||||
this.videoOnly = videoOnly;
|
||||
this.url = url;
|
||||
this.format = format;
|
||||
this.quality = quality;
|
||||
this.mimeType = mimeType;
|
||||
this.videoOnly = videoOnly;
|
||||
}
|
||||
|
||||
public PipedStream(String url, String format, String quality, String mimeType, boolean videoOnly, int bitrate,
|
||||
int initStart, int initEnd, int indexStart, int indexEnd, String codec) {
|
||||
this.url = url;
|
||||
this.format = format;
|
||||
this.quality = quality;
|
||||
this.mimeType = mimeType;
|
||||
this.videoOnly = videoOnly;
|
||||
this.bitrate = bitrate;
|
||||
this.initStart = initStart;
|
||||
this.initEnd = initEnd;
|
||||
this.indexStart = indexStart;
|
||||
this.indexEnd = indexEnd;
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
public PipedStream(String url, String format, String quality, String mimeType, boolean videoOnly, int bitrate,
|
||||
int initStart, int initEnd, int indexStart, int indexEnd, String codec, int width, int height, int fps) {
|
||||
this.url = url;
|
||||
this.format = format;
|
||||
this.quality = quality;
|
||||
this.mimeType = mimeType;
|
||||
this.videoOnly = videoOnly;
|
||||
this.bitrate = bitrate;
|
||||
this.initStart = initStart;
|
||||
this.initEnd = initEnd;
|
||||
this.indexStart = indexStart;
|
||||
this.indexEnd = indexEnd;
|
||||
this.codec = codec;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.fps = fps;
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,15 @@ public class Playlist {
|
||||
public List<StreamItem> relatedStreams;
|
||||
|
||||
public Playlist(String name, String thumbnailUrl, String bannerUrl, String nextpage, String uploader,
|
||||
String uploaderUrl, String uploaderAvatar, int videos, List<StreamItem> relatedStreams) {
|
||||
this.name = name;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.bannerUrl = bannerUrl;
|
||||
this.nextpage = nextpage;
|
||||
this.videos = videos;
|
||||
this.uploader = uploader;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploaderAvatar = uploaderAvatar;
|
||||
this.relatedStreams = relatedStreams;
|
||||
String uploaderUrl, String uploaderAvatar, int videos, List<StreamItem> relatedStreams) {
|
||||
this.name = name;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.bannerUrl = bannerUrl;
|
||||
this.nextpage = nextpage;
|
||||
this.videos = videos;
|
||||
this.uploader = uploader;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploaderAvatar = uploaderAvatar;
|
||||
this.relatedStreams = relatedStreams;
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ public class SearchResults {
|
||||
public ObjectArrayList<SearchItem> items;
|
||||
|
||||
public SearchResults(String nextpage, String id, ObjectArrayList<SearchItem> items) {
|
||||
this.nextpage = nextpage;
|
||||
this.id = id;
|
||||
this.items = items;
|
||||
this.nextpage = nextpage;
|
||||
this.id = id;
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ public class StreamItem {
|
||||
public long duration, views;
|
||||
|
||||
public StreamItem(String url, String title, String thumbnail, String uploaderName, String uploaderUrl,
|
||||
String uploadedDate, long duration, long views) {
|
||||
this.url = url;
|
||||
this.title = title;
|
||||
this.thumbnail = thumbnail;
|
||||
this.uploaderName = uploaderName;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploadedDate = uploadedDate;
|
||||
this.duration = duration;
|
||||
this.views = views;
|
||||
String uploadedDate, long duration, long views) {
|
||||
this.url = url;
|
||||
this.title = title;
|
||||
this.thumbnail = thumbnail;
|
||||
this.uploaderName = uploaderName;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploadedDate = uploadedDate;
|
||||
this.duration = duration;
|
||||
this.views = views;
|
||||
}
|
||||
}
|
||||
|
@ -17,25 +17,25 @@ public class Streams {
|
||||
public boolean livestream;
|
||||
|
||||
public Streams(String title, String description, String uploadDate, String uploader, String uploaderUrl,
|
||||
String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes,
|
||||
List<PipedStream> audioStreams, List<PipedStream> videoStreams, List<StreamItem> relatedStreams,
|
||||
List<Subtitle> subtitles, boolean livestream, String hls) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.uploadDate = uploadDate;
|
||||
this.uploader = uploader;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploaderAvatar = uploaderAvatar;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.duration = duration;
|
||||
this.views = views;
|
||||
this.likes = likes;
|
||||
this.dislikes = dislikes;
|
||||
this.audioStreams = audioStreams;
|
||||
this.videoStreams = videoStreams;
|
||||
this.relatedStreams = relatedStreams;
|
||||
this.subtitles = subtitles;
|
||||
this.livestream = livestream;
|
||||
this.hls = hls;
|
||||
String uploaderAvatar, String thumbnailUrl, long duration, long views, long likes, long dislikes,
|
||||
List<PipedStream> audioStreams, List<PipedStream> videoStreams, List<StreamItem> relatedStreams,
|
||||
List<Subtitle> subtitles, boolean livestream, String hls) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.uploadDate = uploadDate;
|
||||
this.uploader = uploader;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.uploaderAvatar = uploaderAvatar;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.duration = duration;
|
||||
this.views = views;
|
||||
this.likes = likes;
|
||||
this.dislikes = dislikes;
|
||||
this.audioStreams = audioStreams;
|
||||
this.videoStreams = videoStreams;
|
||||
this.relatedStreams = relatedStreams;
|
||||
this.subtitles = subtitles;
|
||||
this.livestream = livestream;
|
||||
this.hls = hls;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public class StreamsPage {
|
||||
public List<StreamItem> relatedStreams;
|
||||
|
||||
public StreamsPage(String nextpage, List<StreamItem> relatedStreams) {
|
||||
this.nextpage = nextpage;
|
||||
this.relatedStreams = relatedStreams;
|
||||
this.nextpage = nextpage;
|
||||
this.relatedStreams = relatedStreams;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ public class Subtitle {
|
||||
public final String url, mimeType;
|
||||
|
||||
public Subtitle(String url, String mimeType) {
|
||||
this.url = url;
|
||||
this.mimeType = mimeType;
|
||||
this.url = url;
|
||||
this.mimeType = mimeType;
|
||||
};
|
||||
}
|
||||
|
@ -5,20 +5,20 @@ public class SearchItem {
|
||||
private String name, thumbnail, url;
|
||||
|
||||
public SearchItem(String name, String thumbnail, String url) {
|
||||
this.name = name;
|
||||
this.thumbnail = thumbnail;
|
||||
this.url = url;
|
||||
this.name = name;
|
||||
this.thumbnail = thumbnail;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return thumbnail;
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,16 @@ public class SearchStream extends SearchItem {
|
||||
private long views, duration;
|
||||
|
||||
public SearchStream(String name, String thumbnail, String url, long views, long duration) {
|
||||
super(name, thumbnail, url);
|
||||
this.views = views;
|
||||
this.duration = duration;
|
||||
super(name, thumbnail, url);
|
||||
this.views = views;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public long getViews() {
|
||||
return views;
|
||||
return views;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user