Skip to content

Commit

Permalink
Use immutable Map factory methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
Isira-Seneviratne committed Jan 2, 2023
1 parent 95cc6ae commit d8ce08d
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
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;

Expand All @@ -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;
Expand Down Expand Up @@ -66,10 +53,12 @@ public String getId(final String url) throws ParsingException {
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"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ public static synchronized String clientId() throws ExtractionException, IOExcep
// 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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
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;
Expand Down Expand Up @@ -61,7 +60,6 @@
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;
Expand Down Expand Up @@ -92,6 +90,11 @@ private 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.
Expand Down Expand Up @@ -554,9 +557,7 @@ public static boolean areHardcodedClientVersionAndKeyValid()
.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)
Expand All @@ -578,9 +579,7 @@ private static void extractClientVersionAndKeyFromSwJs()
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,
Expand Down Expand Up @@ -799,11 +798,9 @@ public static boolean isHardcodedYoutubeMusicKeyValid() throws IOException,
.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
Expand All @@ -826,14 +823,12 @@ public static String[] getYoutubeMusicKey()

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();
Expand Down Expand Up @@ -1176,8 +1171,7 @@ public static JsonObject getJsonPostResponse(final String endpoint,
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="
Expand Down Expand Up @@ -1209,9 +1203,8 @@ private static JsonObject getMobilePostResponse(
@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;
Expand Down Expand Up @@ -1423,60 +1416,67 @@ public static String getIosUserAgent(@Nullable final Localization localization)
+ ")";
}

/**
* 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;
}

/**
* Create a map with the required cookie header.
* @return A singleton map containing the header.
* 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.
*/
public static Map<String, List<String>> getCookieHeader() {
return Collections.singletonMap("Cookie", singletonList(generateConsentCookie()));
private static Map<String, List<String>> getOriginReferrerHeaders(@Nonnull final String url) {
final var urlList = List.of(url);
return Map.of("Origin", urlList, "Referer", urlList);
}

/**
* Add the <code>CONSENT</code> cookie to prevent redirect to <code>consent.youtube.com</code>
* @param headers the headers which should be completed
* 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.
*/
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());
}
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));
}

/**
* Create a map with the required cookie header.
* @return A singleton map containing the header.
*/
public static Map<String, List<String>> getCookieHeader() {
return Map.of("Cookie", List.of(generateConsentCookie()));
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,6 +22,14 @@
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;
Expand All @@ -25,24 +42,6 @@
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.
*
Expand Down Expand Up @@ -583,9 +582,9 @@ public static Response getInitializationResponse(@Nonnull String baseStreamingUr
}
} 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) {
Expand Down Expand Up @@ -705,9 +704,7 @@ private static Response getStreamingWebUrlWithoutRedirects(
@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 = "";

Expand Down
Loading

0 comments on commit d8ce08d

Please sign in to comment.