diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java index 80ac26663..5727150fe 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java @@ -11,10 +11,12 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; + public class Localization implements Serializable { public static final Localization DEFAULT = new Localization("en", "GB"); @@ -26,20 +28,28 @@ public class Localization implements Serializable { /** * @param localizationCodeList a list of localization code, formatted like {@link * #getLocalizationCode()} + * @throws IllegalArgumentException If any of the localizationCodeList is formatted incorrectly + * @return list of Localization objects */ + @Nonnull public static List listFrom(final String... localizationCodeList) { final List toReturn = new ArrayList<>(); for (final String localizationCode : localizationCodeList) { - toReturn.add(fromLocalizationCode(localizationCode)); + toReturn.add(fromLocalizationCode(localizationCode) + .orElseThrow(() -> new IllegalArgumentException( + "Not a localization code: " + localizationCode + ))); } return Collections.unmodifiableList(toReturn); } /** * @param localizationCode a localization code, formatted like {@link #getLocalizationCode()} + * @return A Localization, if the code was valid. */ - public static Localization fromLocalizationCode(final String localizationCode) { - return fromLocale(LocaleCompat.forLanguageTag(localizationCode)); + @Nonnull + public static Optional fromLocalizationCode(final String localizationCode) { + return LocaleCompat.forLanguageTag(localizationCode).map(Localization::fromLocale); } public Localization(@Nonnull final String languageCode, @Nullable final String countryCode) { @@ -61,10 +71,6 @@ public class Localization implements Serializable { return countryCode == null ? "" : countryCode; } - public Locale asLocale() { - return new Locale(getLanguageCode(), getCountryCode()); - } - public static Localization fromLocale(@Nonnull final Locale locale) { return new Localization(locale.getLanguage(), locale.getCountry()); } @@ -72,6 +78,8 @@ public class Localization implements Serializable { /** * Return a formatted string in the form of: {@code language-Country}, or * just {@code language} if country is {@code null}. + * + * @return A correctly formatted localizationCode for this localization. */ public String getLocalizationCode() { return languageCode + (countryCode == null ? "" : "-" + countryCode); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java index 9f299a71a..5e7641f0f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java @@ -130,7 +130,10 @@ public class MediaCCCStreamExtractor extends StreamExtractor { // track with multiple languages, so there is no specific language for this stream // Don't set the audio language in this case if (language != null && !language.contains("-")) { - builder.setAudioLocale(LocaleCompat.forLanguageTag(language)); + builder.setAudioLocale(LocaleCompat.forLanguageTag(language).orElseThrow(() -> + new ExtractionException( + "Cannot convert this language to a locale: " + language) + )); } // Not checking containsSimilarStream here, since MediaCCC does not provide enough diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java index e77ea16b4..fd6b94445 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java @@ -190,7 +190,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { try { // Premiered 20 hours ago final TimeAgoParser timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor( - Localization.fromLocalizationCode("en")); + Localization.fromLocalizationCode("en").get()); final OffsetDateTime parsedTime = timeAgoParser.parse(time).offsetDateTime(); return DateTimeFormatter.ISO_LOCAL_DATE.format(parsedTime); } catch (final Exception ignored) { @@ -1378,8 +1378,13 @@ public class YoutubeStreamExtractor extends StreamExtractor { final int audioTrackIdLastLocaleCharacter = audioTrackId.indexOf("."); if (audioTrackIdLastLocaleCharacter != -1) { // Audio tracks IDs are in the form LANGUAGE_CODE.TRACK_NUMBER - itagItem.setAudioLocale(LocaleCompat.forLanguageTag( - audioTrackId.substring(0, audioTrackIdLastLocaleCharacter))); + @Nullable final Locale locale = + LocaleCompat.forLanguageTag( + audioTrackId.substring(0, audioTrackIdLastLocaleCharacter + )).orElse(null); + if (locale != null) { + itagItem.setAudioLocale(locale); + } } itagItem.setAudioTrackType(YoutubeParsingHelper.extractAudioTrackType(streamUrl)); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/SubtitlesStream.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/SubtitlesStream.java index 983d20ce9..278b4e9a6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/SubtitlesStream.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/SubtitlesStream.java @@ -231,7 +231,9 @@ public final class SubtitlesStream extends Stream { final boolean autoGenerated, @Nullable final String manifestUrl) { super(id, content, isUrl, mediaFormat, deliveryMethod, manifestUrl); - this.locale = LocaleCompat.forLanguageTag(languageCode); + this.locale = LocaleCompat.forLanguageTag(languageCode).orElseThrow( + () -> new IllegalArgumentException( + "not a valid locale language code: " + languageCode)); this.code = languageCode; this.format = mediaFormat; this.autoGenerated = autoGenerated; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/LocaleCompat.java b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/LocaleCompat.java index a8f85f47b..082a56824 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/LocaleCompat.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/LocaleCompat.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.extractor.utils; import java.util.Locale; +import java.util.Optional; /** * This class contains a simple implementation of {@link Locale#forLanguageTag(String)} for Android @@ -15,29 +16,29 @@ public final class LocaleCompat { // Source: The AndroidX LocaleListCompat class's private forLanguageTagCompat() method. // Use Locale.forLanguageTag() on Android API level >= 21 / Java instead. - public static Locale forLanguageTag(final String str) { + public static Optional forLanguageTag(final String str) { if (str.contains("-")) { final String[] args = str.split("-", -1); if (args.length > 2) { - return new Locale(args[0], args[1], args[2]); + return Optional.of(new Locale(args[0], args[1], args[2])); } else if (args.length > 1) { - return new Locale(args[0], args[1]); + return Optional.of(new Locale(args[0], args[1])); } else if (args.length == 1) { - return new Locale(args[0]); + return Optional.of(new Locale(args[0])); } } else if (str.contains("_")) { final String[] args = str.split("_", -1); if (args.length > 2) { - return new Locale(args[0], args[1], args[2]); + return Optional.of(new Locale(args[0], args[1], args[2])); } else if (args.length > 1) { - return new Locale(args[0], args[1]); + return Optional.of(new Locale(args[0], args[1])); } else if (args.length == 1) { - return new Locale(args[0]); + return Optional.of(new Locale(args[0])); } } else { - return new Locale(str); + return Optional.of(new Locale(str)); } - throw new IllegalArgumentException("Can not parse language tag: [" + str + "]"); + return Optional.empty(); } }