Use immutable Map factory methods.
This commit is contained in:
parent
95cc6aefbb
commit
d8ce08d969
|
@ -4,8 +4,6 @@ import org.schabi.newpipe.extractor.ServiceList;
|
|||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -14,27 +12,16 @@ public final class PeertubeTrendingLinkHandlerFactory extends ListLinkHandlerFac
|
|||
private static final PeertubeTrendingLinkHandlerFactory INSTANCE
|
||||
= new PeertubeTrendingLinkHandlerFactory();
|
||||
|
||||
public static final Map<String, String> KIOSK_MAP;
|
||||
public static final Map<String, String> REVERSE_KIOSK_MAP;
|
||||
public static final String KIOSK_TRENDING = "Trending";
|
||||
public static final String KIOSK_MOST_LIKED = "Most liked";
|
||||
public static final String KIOSK_RECENT = "Recently added";
|
||||
public static final String KIOSK_LOCAL = "Local";
|
||||
|
||||
static {
|
||||
final Map<String, String> map = new HashMap<>();
|
||||
map.put(KIOSK_TRENDING, "%s/api/v1/videos?sort=-trending");
|
||||
map.put(KIOSK_MOST_LIKED, "%s/api/v1/videos?sort=-likes");
|
||||
map.put(KIOSK_RECENT, "%s/api/v1/videos?sort=-publishedAt");
|
||||
map.put(KIOSK_LOCAL, "%s/api/v1/videos?sort=-publishedAt&filter=local");
|
||||
KIOSK_MAP = Collections.unmodifiableMap(map);
|
||||
|
||||
final Map<String, String> reverseMap = new HashMap<>();
|
||||
for (final Map.Entry<String, String> entry : KIOSK_MAP.entrySet()) {
|
||||
reverseMap.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
REVERSE_KIOSK_MAP = Collections.unmodifiableMap(reverseMap);
|
||||
}
|
||||
public static final Map<String, String> KIOSK_MAP = Map.of(
|
||||
KIOSK_TRENDING, "%s/api/v1/videos?sort=-trending",
|
||||
KIOSK_MOST_LIKED, "%s/api/v1/videos?sort=-likes",
|
||||
KIOSK_RECENT, "%s/api/v1/videos?sort=-publishedAt",
|
||||
KIOSK_LOCAL, "%s/api/v1/videos?sort=-publishedAt&filter=local");
|
||||
|
||||
public static PeertubeTrendingLinkHandlerFactory getInstance() {
|
||||
return INSTANCE;
|
||||
|
@ -66,10 +53,12 @@ public final class PeertubeTrendingLinkHandlerFactory extends ListLinkHandlerFac
|
|||
return KIOSK_RECENT;
|
||||
} else if (cleanUrl.contains("/videos/local")) {
|
||||
return KIOSK_LOCAL;
|
||||
} else if (REVERSE_KIOSK_MAP.containsKey(cleanUrl)) {
|
||||
return REVERSE_KIOSK_MAP.get(cleanUrl);
|
||||
} else {
|
||||
throw new ParsingException("no id found for this url");
|
||||
return KIOSK_MAP.entrySet().stream()
|
||||
.filter(entry -> cleanUrl.equals(entry.getValue()))
|
||||
.findFirst()
|
||||
.map(Map.Entry::getKey)
|
||||
.orElseThrow(() -> new ParsingException("no id found for this url"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,7 @@ public final class SoundcloudParsingHelper {
|
|||
// The one containing the client id will likely be the last one
|
||||
Collections.reverse(possibleScripts);
|
||||
|
||||
final Map<String, List<String>> headers = Collections.singletonMap("Range",
|
||||
Collections.singletonList("bytes=0-50000"));
|
||||
final var headers = Map.of("Range", List.of("bytes=0-50000"));
|
||||
|
||||
for (final Element element : possibleScripts) {
|
||||
final String srcUrl = element.attr("src");
|
||||
|
|
|
@ -25,7 +25,6 @@ import static org.schabi.newpipe.extractor.utils.Utils.HTTP;
|
|||
import static org.schabi.newpipe.extractor.utils.Utils.HTTPS;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.getStringResultFromRegexArray;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonBuilder;
|
||||
|
@ -61,7 +60,6 @@ import java.time.OffsetDateTime;
|
|||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -92,6 +90,11 @@ public final class YoutubeParsingHelper {
|
|||
public static final String YOUTUBEI_V1_GAPIS_URL =
|
||||
"https://youtubei.googleapis.com/youtubei/v1/";
|
||||
|
||||
/**
|
||||
* The base URL of YouTube Music.
|
||||
*/
|
||||
private static final String YOUTUBE_MUSIC_URL = "https://music.youtube.com";
|
||||
|
||||
/**
|
||||
* A parameter to disable pretty-printed response of InnerTube requests, to reduce response
|
||||
* sizes.
|
||||
|
@ -554,9 +557,7 @@ public final class YoutubeParsingHelper {
|
|||
.end().done().getBytes(StandardCharsets.UTF_8);
|
||||
// @formatter:on
|
||||
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("X-YouTube-Client-Name", singletonList("1"));
|
||||
headers.put("X-YouTube-Client-Version", singletonList(HARDCODED_CLIENT_VERSION));
|
||||
final var headers = getClientHeaders("1", HARDCODED_CLIENT_VERSION);
|
||||
|
||||
// This endpoint is fetched by the YouTube website to get the items of its main menu and is
|
||||
// pretty lightweight (around 30kB)
|
||||
|
@ -578,9 +579,7 @@ public final class YoutubeParsingHelper {
|
|||
return;
|
||||
}
|
||||
final String url = "https://www.youtube.com/sw.js";
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("Origin", singletonList("https://www.youtube.com"));
|
||||
headers.put("Referer", singletonList("https://www.youtube.com"));
|
||||
final var headers = getOriginReferrerHeaders("https://www.youtube.com");
|
||||
final String response = getDownloader().get(url, headers).responseBody();
|
||||
try {
|
||||
clientVersion = getStringResultFromRegexArray(response,
|
||||
|
@ -799,11 +798,9 @@ public final class YoutubeParsingHelper {
|
|||
.end().done().getBytes(StandardCharsets.UTF_8);
|
||||
// @formatter:on
|
||||
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("X-YouTube-Client-Name", singletonList(HARDCODED_YOUTUBE_MUSIC_KEY[1]));
|
||||
headers.put("X-YouTube-Client-Version", singletonList(HARDCODED_YOUTUBE_MUSIC_KEY[2]));
|
||||
headers.put("Origin", singletonList("https://music.youtube.com"));
|
||||
headers.put("Referer", singletonList("https://music.youtube.com"));
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders(YOUTUBE_MUSIC_URL));
|
||||
headers.putAll(getClientHeaders(HARDCODED_YOUTUBE_MUSIC_KEY[1],
|
||||
HARDCODED_YOUTUBE_MUSIC_KEY[2]));
|
||||
|
||||
final Response response = getDownloader().postWithContentTypeJson(url, headers, json);
|
||||
// Ensure to have a valid response
|
||||
|
@ -826,14 +823,12 @@ public final class YoutubeParsingHelper {
|
|||
|
||||
try {
|
||||
final String url = "https://music.youtube.com/sw.js";
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("Origin", singletonList("https://music.youtube.com"));
|
||||
headers.put("Referer", singletonList("https://music.youtube.com"));
|
||||
final var headers = getOriginReferrerHeaders("https://music.youtube.com");
|
||||
final String response = getDownloader().get(url, headers).responseBody();
|
||||
musicClientVersion = getStringResultFromRegexArray(response,
|
||||
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
|
||||
musicKey = getStringResultFromRegexArray(response, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
musicClientName = Parser.matchGroup1(INNERTUBE_CLIENT_NAME_REGEX, response);
|
||||
musicClientVersion = getStringResultFromRegexArray(response,
|
||||
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
|
||||
musicKey = getStringResultFromRegexArray(response, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
musicClientName = Parser.matchGroup1(INNERTUBE_CLIENT_NAME_REGEX, response);
|
||||
} catch (final Exception e) {
|
||||
final String url = "https://music.youtube.com/?ucbcb=1";
|
||||
final String html = getDownloader().get(url, getCookieHeader()).responseBody();
|
||||
|
@ -1176,8 +1171,7 @@ public final class YoutubeParsingHelper {
|
|||
final byte[] body,
|
||||
final Localization localization)
|
||||
throws IOException, ExtractionException {
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
addYouTubeHeaders(headers);
|
||||
final var headers = getYouTubeHeaders();
|
||||
|
||||
return JsonUtils.toJsonObject(getValidJsonResponseBody(
|
||||
getDownloader().postWithContentTypeJson(YOUTUBEI_V1_URL + endpoint + "?key="
|
||||
|
@ -1209,9 +1203,8 @@ public final class YoutubeParsingHelper {
|
|||
@Nonnull final String userAgent,
|
||||
@Nonnull final String innerTubeApiKey,
|
||||
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("User-Agent", singletonList(userAgent));
|
||||
headers.put("X-Goog-Api-Format-Version", singletonList("2"));
|
||||
final var headers = Map.of("User-Agent", List.of(userAgent),
|
||||
"X-Goog-Api-Format-Version", List.of("2"));
|
||||
|
||||
final String baseEndpointUrl = YOUTUBEI_V1_GAPIS_URL + endpoint + "?key=" + innerTubeApiKey
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
@ -1423,40 +1416,59 @@ public final class YoutubeParsingHelper {
|
|||
+ ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} containing the required YouTube Music headers.
|
||||
*/
|
||||
@Nonnull
|
||||
public static Map<String, List<String>> getYoutubeMusicHeaders() {
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("X-YouTube-Client-Name", Collections.singletonList(youtubeMusicKey[1]));
|
||||
headers.put("X-YouTube-Client-Version", Collections.singletonList(youtubeMusicKey[2]));
|
||||
headers.put("Origin", Collections.singletonList("https://music.youtube.com"));
|
||||
headers.put("Referer", Collections.singletonList("https://music.youtube.com"));
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders(YOUTUBE_MUSIC_URL));
|
||||
headers.putAll(getClientHeaders(youtubeMusicKey[1], youtubeMusicKey[2]));
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required headers and cookies to an existing headers Map.
|
||||
* @see #addClientInfoHeaders(Map)
|
||||
* @see #addCookieHeader(Map)
|
||||
* Returns a {@link Map} containing the required YouTube headers.
|
||||
*/
|
||||
public static void addYouTubeHeaders(final Map<String, List<String>> headers)
|
||||
throws IOException, ExtractionException {
|
||||
addClientInfoHeaders(headers);
|
||||
addCookieHeader(headers);
|
||||
public static Map<String, List<String>> getYouTubeHeaders()
|
||||
throws ExtractionException, IOException {
|
||||
final var headers = getClientInfoHeaders();
|
||||
headers.put("Cookie", List.of(generateConsentCookie()));
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the <code>X-YouTube-Client-Name</code>, <code>X-YouTube-Client-Version</code>,
|
||||
* <code>Origin</code>, and <code>Referer</code> headers.
|
||||
* @param headers The headers which should be completed
|
||||
* Returns a {@link Map} containing the {@code X-YouTube-Client-Name},
|
||||
* {@code X-YouTube-Client-Version}, {@code Origin}, and {@code Referer} headers.
|
||||
*/
|
||||
public static void addClientInfoHeaders(@Nonnull final Map<String, List<String>> headers)
|
||||
throws IOException, ExtractionException {
|
||||
headers.computeIfAbsent("Origin", k -> singletonList("https://www.youtube.com"));
|
||||
headers.computeIfAbsent("Referer", k -> singletonList("https://www.youtube.com"));
|
||||
headers.computeIfAbsent("X-YouTube-Client-Name", k -> singletonList("1"));
|
||||
if (headers.get("X-YouTube-Client-Version") == null) {
|
||||
headers.put("X-YouTube-Client-Version", singletonList(getClientVersion()));
|
||||
}
|
||||
public static Map<String, List<String>> getClientInfoHeaders()
|
||||
throws ExtractionException, IOException {
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders("https://www.youtube.com"));
|
||||
headers.putAll(getClientHeaders("1", getClientVersion()));
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable {@link Map} containing the {@code Origin} and {@code Referer}
|
||||
* headers set to the given URL.
|
||||
*
|
||||
* @param url The URL to be set as the origin and referrer.
|
||||
*/
|
||||
private static Map<String, List<String>> getOriginReferrerHeaders(@Nonnull final String url) {
|
||||
final var urlList = List.of(url);
|
||||
return Map.of("Origin", urlList, "Referer", urlList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable {@link Map} containing the {@code X-YouTube-Client-Name} and
|
||||
* {@code X-YouTube-Client-Version} headers.
|
||||
*
|
||||
* @param name The X-YouTube-Client-Name value.
|
||||
* @param version X-YouTube-Client-Version value.
|
||||
*/
|
||||
private static Map<String, List<String>> getClientHeaders(@Nonnull final String name,
|
||||
@Nonnull final String version) {
|
||||
return Map.of("X-YouTube-Client-Name", List.of(name),
|
||||
"X-YouTube-Client-Version", List.of(version));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1464,19 +1476,7 @@ public final class YoutubeParsingHelper {
|
|||
* @return A singleton map containing the header.
|
||||
*/
|
||||
public static Map<String, List<String>> getCookieHeader() {
|
||||
return Collections.singletonMap("Cookie", singletonList(generateConsentCookie()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the <code>CONSENT</code> cookie to prevent redirect to <code>consent.youtube.com</code>
|
||||
* @param headers the headers which should be completed
|
||||
*/
|
||||
public static void addCookieHeader(@Nonnull final Map<String, List<String>> headers) {
|
||||
if (headers.get("Cookie") == null) {
|
||||
headers.put("Cookie", Collections.singletonList(generateConsentCookie()));
|
||||
} else {
|
||||
headers.get("Cookie").add(generateConsentCookie());
|
||||
}
|
||||
return Map.of("Cookie", List.of(generateConsentCookie()));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
package org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators;
|
||||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getAndroidUserAgent;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getClientInfoHeaders;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getIosUserAgent;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isIosStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isTvHtml5SimplyEmbeddedPlayerStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||
|
@ -13,6 +22,14 @@ import org.w3c.dom.DOMException;
|
|||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
|
@ -25,24 +42,6 @@ import javax.xml.transform.TransformerFactory;
|
|||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getAndroidUserAgent;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getIosUserAgent;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isIosStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isTvHtml5SimplyEmbeddedPlayerStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* Utilities and constants for YouTube DASH manifest creators.
|
||||
*
|
||||
|
@ -583,9 +582,9 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
}
|
||||
} else if (isAndroidStreamingUrl || isIosStreamingUrl) {
|
||||
try {
|
||||
final Map<String, List<String>> headers = Collections.singletonMap("User-Agent",
|
||||
Collections.singletonList(isAndroidStreamingUrl
|
||||
? getAndroidUserAgent(null) : getIosUserAgent(null)));
|
||||
final var headers = Map.of("User-Agent",
|
||||
List.of(isAndroidStreamingUrl ? getAndroidUserAgent(null)
|
||||
: getIosUserAgent(null)));
|
||||
final byte[] emptyBody = "".getBytes(StandardCharsets.UTF_8);
|
||||
return downloader.post(baseStreamingUrl, headers, emptyBody);
|
||||
} catch (final IOException | ExtractionException e) {
|
||||
|
@ -705,9 +704,7 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
@Nonnull final String responseMimeTypeExpected)
|
||||
throws CreationException {
|
||||
try {
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("Origin", Collections.singletonList("https://www.youtube.com"));
|
||||
headers.put("Referer", Collections.singletonList("https://www.youtube.com"));
|
||||
final var headers = getClientInfoHeaders();
|
||||
|
||||
String responseMimeType = "";
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
|||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.addYouTubeHeaders;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractCookieValue;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractPlaylistTypeFromPlaylistId;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getValidJsonResponseBody;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getYouTubeHeaders;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.getQueryValue;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
@ -88,9 +88,8 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
|
|||
|
||||
final byte[] body = JsonWriter.string(jsonBody.done()).getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
// Cookie is required due to consent
|
||||
addYouTubeHeaders(headers);
|
||||
final var headers = getYouTubeHeaders();
|
||||
|
||||
final Response response = getDownloader().postWithContentTypeJson(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
|
@ -222,9 +221,8 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
|
|||
}
|
||||
|
||||
final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
|
||||
final Map<String, List<String>> headers = new HashMap<>();
|
||||
// Cookie is required due to consent
|
||||
addYouTubeHeaders(headers);
|
||||
final var headers = getYouTubeHeaders();
|
||||
|
||||
final Response response = getDownloader().postWithContentTypeJson(page.getUrl(), headers,
|
||||
page.getBody(), getExtractorLocalization());
|
||||
|
|
|
@ -14,6 +14,7 @@ import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
|||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
|
||||
import org.schabi.newpipe.extractor.Page;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||
|
@ -29,11 +30,12 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||
// Names of some objects in JSON response frequently used in this class
|
||||
private static final String PLAYLIST_VIDEO_RENDERER = "playlistVideoRenderer";
|
||||
|
|
Loading…
Reference in New Issue