From 180836c180780e470ef83ece140bd20582fb75e2 Mon Sep 17 00:00:00 2001 From: wojcik-online Date: Wed, 2 Oct 2019 02:02:01 -0300 Subject: [PATCH 1/9] Base Implementation: Parse the upload date of StreamInfoItems In the format '2 days ago' (in English) on a YouTube channel page. (Parser extensible to other pages.) --- .../newpipe/extractor/StreamingService.java | 10 +- .../soundcloud/SoundcloudParsingHelper.java | 21 ++- .../soundcloud/SoundcloudStreamExtractor.java | 2 +- .../SoundcloudStreamInfoItemExtractor.java | 17 +- .../extractors/YoutubeChannelExtractor.java | 5 +- .../extractors/YoutubePlaylistExtractor.java | 7 +- .../extractors/YoutubeSearchExtractor.java | 3 +- .../extractors/YoutubeStreamExtractor.java | 6 +- .../YoutubeStreamInfoItemExtractor.java | 39 ++++- .../extractors/YoutubeTrendingExtractor.java | 5 +- .../extractor/stream/StreamInfoItem.java | 39 +++-- .../stream/StreamInfoItemExtractor.java | 30 +++- .../stream/StreamInfoItemsCollector.java | 7 +- .../extractor/stream/TimeAgoParser.java | 158 ++++++++++++++++++ .../java/org/schabi/newpipe/Downloader.java | 2 + .../extractor/services/DefaultTests.java | 9 + 16 files changed, 316 insertions(+), 44 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/stream/TimeAgoParser.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java index 26e84da97..c613d34f2 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java @@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.utils.Localization; @@ -222,7 +223,7 @@ public abstract class StreamingService { public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) throws ExtractionException { return getChannelExtractor(linkHandler, NewPipe.getPreferredLocalization()); } - + public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) throws ExtractionException { return getPlaylistExtractor(linkHandler, NewPipe.getPreferredLocalization()); } @@ -230,7 +231,7 @@ public abstract class StreamingService { public StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException { return getStreamExtractor(linkHandler, NewPipe.getPreferredLocalization()); } - + public CommentsExtractor getCommentsExtractor(ListLinkHandler urlIdHandler) throws ExtractionException { return getCommentsExtractor(urlIdHandler, NewPipe.getPreferredLocalization()); } @@ -287,7 +288,7 @@ public abstract class StreamingService { public StreamExtractor getStreamExtractor(String url) throws ExtractionException { return getStreamExtractor(getStreamLHFactory().fromUrl(url), NewPipe.getPreferredLocalization()); } - + public CommentsExtractor getCommentsExtractor(String url) throws ExtractionException { ListLinkHandlerFactory llhf = getCommentsLHFactory(); if(null == llhf) { @@ -296,6 +297,9 @@ public abstract class StreamingService { return getCommentsExtractor(llhf.fromUrl(url), NewPipe.getPreferredLocalization()); } + public TimeAgoParser getTimeAgoParser() { + return new TimeAgoParser(TimeAgoParser.DEFAULT_AGO_PHRASES); + } /** * Figures out where the link is pointing to (a channel, a video, a playlist, etc.) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java index 96b7fcea7..d4a8123c0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java @@ -79,23 +79,22 @@ public class SoundcloudParsingHelper { return dl.head(apiUrl).getResponseCode() == 200; } - public static String toDateString(String time) throws ParsingException { + static Date parseDate(String time) throws ParsingException { try { - Date date; - // Have two date formats, one for the 'api.soundc...' and the other 'api-v2.soundc...'. + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(time); + } catch (ParseException e1) { try { - date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(time); - } catch (Exception e) { - date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(time); + return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(time); + } catch (ParseException e2) { + throw new ParsingException(e1.getMessage(), e2); } - - SimpleDateFormat newDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - return newDateFormat.format(date); - } catch (ParseException e) { - throw new ParsingException(e.getMessage(), e); } } + static String toTextualDate(String time) throws ParsingException { + return new SimpleDateFormat("yyyy-MM-dd").format(parseDate(time)); + } + /** * Call the endpoint "/resolve" of the api.

* diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java index f5860d835..b842d85af 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java @@ -51,7 +51,7 @@ public class SoundcloudStreamExtractor extends StreamExtractor { @Nonnull @Override public String getUploadDate() throws ParsingException { - return SoundcloudParsingHelper.toDateString(track.getString("created_at")); + return SoundcloudParsingHelper.toTextualDate(track.getString("created_at")); } @Nonnull diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java index 09455e193..a81421f01 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java @@ -5,6 +5,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; +import java.util.Calendar; + import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps; public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtractor { @@ -41,8 +43,19 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto } @Override - public String getUploadDate() throws ParsingException { - return SoundcloudParsingHelper.toDateString(itemObject.getString("created_at")); + public String getTextualUploadDate() throws ParsingException { + return SoundcloudParsingHelper.toTextualDate(getCreatedAt()); + } + + @Override + public Calendar getUploadDate() throws ParsingException { + Calendar uploadTime = Calendar.getInstance(); + uploadTime.setTime(SoundcloudParsingHelper.parseDate(getCreatedAt())); + return uploadTime; + } + + private String getCreatedAt() { + return itemObject.getString("created_at"); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java index 9641d3931..14c5a9ed1 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java @@ -18,6 +18,7 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.utils.DonationLinkHelper; import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Parser; @@ -53,6 +54,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor { private static final String CHANNEL_FEED_BASE = "https://www.youtube.com/feeds/videos.xml?channel_id="; private static final String CHANNEL_URL_PARAMETERS = "/videos?view=0&flow=list&sort=dd&live_view=10000&gl=US&hl=en"; + private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); + private Document doc; public YoutubeChannelExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { @@ -230,7 +233,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor { final String uploaderUrl = getUrl(); for (final Element li : element.children()) { if (li.select("div[class=\"feed-item-dismissable\"]").first() != null) { - collector.commit(new YoutubeStreamInfoItemExtractor(li) { + collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { @Override public String getUrl() throws ParsingException { try { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java index 4480b38af..0d5668e9f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java @@ -18,6 +18,7 @@ import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingH import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.stream.StreamType; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Utils; @@ -28,6 +29,8 @@ import java.io.IOException; @SuppressWarnings("WeakerAccess") public class YoutubePlaylistExtractor extends PlaylistExtractor { + private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); + private Document doc; public YoutubePlaylistExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { @@ -192,7 +195,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { continue; } - collector.commit(new YoutubeStreamInfoItemExtractor(li) { + collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { public Element uploaderLink; @Override @@ -258,7 +261,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { } @Override - public String getUploadDate() throws ParsingException { + public String getTextualUploadDate() throws ParsingException { return ""; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java index 0a954607f..c3f234aaf 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java @@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; @@ -129,7 +130,7 @@ public class YoutubeSearchExtractor extends SearchExtractor { // video item type } else if ((el = item.select("div[class*=\"yt-lockup-video\"]").first()) != null) { - collector.commit(new YoutubeStreamInfoItemExtractor(el)); + collector.commit(new YoutubeStreamInfoItemExtractor(el, getService().getTimeAgoParser())); } else if ((el = item.select("div[class*=\"yt-lockup-channel\"]").first()) != null) { collector.commit(new YoutubeChannelInfoItemExtractor(el)); } else if ((el = item.select("div[class*=\"yt-lockup-playlist\"]").first()) != null && 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 fa866cd5b..4c33a258c 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 @@ -75,6 +75,8 @@ public class YoutubeStreamExtractor extends StreamExtractor { /*//////////////////////////////////////////////////////////////////////////*/ + private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); + private Document doc; @Nullable private JsonObject playerArgs; @@ -932,7 +934,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { * This is encapsulated in a StreamInfoItem object, which is a subset of the fields in a full StreamInfo. */ private StreamInfoItemExtractor extractVideoPreviewInfo(final Element li) { - return new YoutubeStreamInfoItemExtractor(li) { + return new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { @Override public String getUrl() throws ParsingException { @@ -959,7 +961,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { } @Override - public String getUploadDate() throws ParsingException { + public String getTextualUploadDate() throws ParsingException { return ""; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 5bfeaa38e..763c25380 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -1,12 +1,17 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.utils.Utils; +import javax.annotation.Nullable; +import java.util.Calendar; + /* * Copyright (C) Christian Schabesberger 2016 * YoutubeStreamInfoItemExtractor.java is part of NewPipe. @@ -28,9 +33,18 @@ import org.schabi.newpipe.extractor.utils.Utils; public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { private final Element item; + private final TimeAgoParser timeAgoParser; - public YoutubeStreamInfoItemExtractor(Element item) { + private String cachedUploadDate; + + /** + * Creates an extractor of StreamInfoItems from a YouTube page. + * @param item The page element + * @param timeAgoParser A parser of the textual dates or {@code null}. + */ + public YoutubeStreamInfoItemExtractor(Element item, @Nullable TimeAgoParser timeAgoParser) { this.item = item; + this.timeAgoParser = timeAgoParser; } @Override @@ -126,20 +140,35 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { } @Override - public String getUploadDate() throws ParsingException { + public String getTextualUploadDate() throws ParsingException { + if (cachedUploadDate != null) { + return cachedUploadDate; + } + try { Element meta = item.select("div[class=\"yt-lockup-meta\"]").first(); if (meta == null) return ""; - Element li = meta.select("li").first(); - if(li == null) return ""; + final Elements li = meta.select("li"); + if (li.isEmpty()) return ""; - return meta.select("li").first().text(); + return cachedUploadDate = li.first().text(); } catch (Exception e) { throw new ParsingException("Could not get upload date", e); } } + @Override + public Calendar getUploadDate() throws ParsingException { + String textualUploadDate = getTextualUploadDate(); + if (timeAgoParser != null + && textualUploadDate != null && !"".equals(textualUploadDate)) { + return timeAgoParser.parse(textualUploadDate); + } else { + return null; + } + } + @Override public long getViewCount() throws ParsingException { String input; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java index dc7cc7e69..31e743542 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java @@ -35,12 +35,15 @@ import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingH import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import javax.annotation.Nonnull; import java.io.IOException; public class YoutubeTrendingExtractor extends KioskExtractor { + private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); + private Document doc; public YoutubeTrendingExtractor(StreamingService service, @@ -93,7 +96,7 @@ public class YoutubeTrendingExtractor extends KioskExtractor { for(Element ul : uls) { for(final Element li : ul.children()) { final Element el = li.select("div[class*=\"yt-lockup-dismissable\"]").first(); - collector.commit(new YoutubeStreamInfoItemExtractor(li) { + collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { @Override public String getUrl() throws ParsingException { try { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java index 375739160..3f786baec 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java @@ -22,6 +22,8 @@ package org.schabi.newpipe.extractor.stream; import org.schabi.newpipe.extractor.InfoItem; +import java.util.Calendar; + /** * Info object for previews of unopened videos, eg search results, related videos */ @@ -29,7 +31,8 @@ public class StreamInfoItem extends InfoItem { private final StreamType streamType; private String uploaderName; - private String uploadDate; + private String textualUploadDate; + private Calendar uploadDate; private long viewCount = -1; private long duration = -1; @@ -52,14 +55,6 @@ public class StreamInfoItem extends InfoItem { this.uploaderName = uploader_name; } - public String getUploadDate() { - return uploadDate; - } - - public void setUploadDate(String upload_date) { - this.uploadDate = upload_date; - } - public long getViewCount() { return viewCount; } @@ -84,12 +79,36 @@ public class StreamInfoItem extends InfoItem { this.uploaderUrl = uploaderUrl; } + /** + * @return The original textual upload date as returned by the streaming service. + * @see #getUploadDate() + */ + public String getTextualUploadDate() { + return textualUploadDate; + } + + public void setTextualUploadDate(String upload_date) { + this.textualUploadDate = upload_date; + } + + /** + * @return The (approximated) date and time this item was uploaded or {@code null}. + * @see #getTextualUploadDate() + */ + public Calendar getUploadDate() { + return uploadDate; + } + + public void setUploadDate(Calendar uploadDate) { + this.uploadDate = uploadDate; + } + @Override public String toString() { return "StreamInfoItem{" + "streamType=" + streamType + ", uploaderName='" + uploaderName + '\'' + - ", uploadDate='" + uploadDate + '\'' + + ", textualUploadDate='" + textualUploadDate + '\'' + ", viewCount=" + viewCount + ", duration=" + duration + ", uploaderUrl='" + uploaderUrl + '\'' + diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java index 3bc3a9e3c..4184131e3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java @@ -3,6 +3,8 @@ package org.schabi.newpipe.extractor.stream; import org.schabi.newpipe.extractor.InfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import java.util.Calendar; + /* * Created by Christian Schabesberger on 28.02.16. * @@ -64,10 +66,30 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor { String getUploaderUrl() throws ParsingException; /** - * Extract the uploader name - * @return the uploader name - * @throws ParsingException thrown if there is an error in the extraction + * Extract the textual upload date of this item. + * The original textual date provided by the service may be used if it is short; + * otherwise the format "yyyy-MM-dd" or an locale specific version is preferred. + * + * @return The original textual upload date. + * @throws ParsingException if there is an error in the extraction + * @see #getUploadDate() */ - String getUploadDate() throws ParsingException; + String getTextualUploadDate() throws ParsingException; + + /** + * Extracts the upload date and time of this item and parses it. + *

+ * If the service doesn't provide an exact time, an approximation can be returned. + * The approximation should be marked by setting seconds and milliseconds to zero. + *
+ * If the service doesn't provide any date at all, then {@code null} should be returned. + *

+ * + * @return The (approximated) date and time this item was uploaded or {@code null}. + * @throws ParsingException if there is an error in the extraction + * or the extracted date couldn't be parsed. + * @see #getTextualUploadDate() + */ + Calendar getUploadDate() throws ParsingException; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java index b838e7ac8..85dce8f0b 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java @@ -61,10 +61,15 @@ public class StreamInfoItemsCollector extends InfoItemsCollector> DEFAULT_AGO_PHRASES = + new EnumMap<>(TimeAgoUnit.class); + + private final Map> agoPhrases; + + private final Calendar consistentNow; + + /** + * Creates a helper to parse upload dates in the format '2 days ago'. + *

+ * Instantiate a new {@link TimeAgoParser} every time you extract a new batch of items. + *

+ * @param agoPhrases A set of phrases how to recognize the time units in a given language. + */ + public TimeAgoParser(Map> agoPhrases) { + this.agoPhrases = agoPhrases; + consistentNow = Calendar.getInstance(); + } + + /** + * Parses a textual date in the format '2 days ago' into a Calendar representation. + * Beginning with days ago, marks the date as approximated by setting minutes, seconds + * and milliseconds to 0. + * @param textualDate The original date as provided by the streaming service + * @return The parsed (approximated) time + * @throws ParsingException if the time unit could not be recognized + */ + public Calendar parse(String textualDate) throws ParsingException { + int timeAgoAmount; + try { + timeAgoAmount = parseTimeAgoAmount(textualDate); + } catch (NumberFormatException e) { + // If there is no valid number in the textual date, + // assume it is 1 (as in 'a second ago'). + timeAgoAmount = 1; + } + + TimeAgoUnit timeAgoUnit = parseTimeAgoUnit(textualDate); + return getCalendar(timeAgoAmount, timeAgoUnit); + } + + private int parseTimeAgoAmount(String textualDate) throws NumberFormatException { + String timeValueStr = textualDate.replaceAll("\\D+", ""); + return Integer.parseInt(timeValueStr); + } + + private TimeAgoUnit parseTimeAgoUnit(String textualDate) throws ParsingException { + for (TimeAgoUnit timeAgoUnit : agoPhrases.keySet()) { + for (String agoPhrase : agoPhrases.get(timeAgoUnit)) { + if (textualDate.toLowerCase().contains(agoPhrase.toLowerCase())){ + return timeAgoUnit; + } + } + } + + throw new ParsingException("Unable to parse the date: " + textualDate); + } + + private Calendar getCalendar(int timeAgoAmount, TimeAgoUnit timeAgoUnit) { + Calendar calendarTime = getNow(); + + switch (timeAgoUnit) { + case SECONDS: + calendarTime.add(Calendar.SECOND, -timeAgoAmount); + break; + + case MINUTES: + calendarTime.add(Calendar.MINUTE, -timeAgoAmount); + break; + + case HOURS: + calendarTime.add(Calendar.HOUR_OF_DAY, -timeAgoAmount); + break; + + case DAYS: + calendarTime.add(Calendar.DAY_OF_MONTH, -timeAgoAmount); + markApproximatedTime(calendarTime); + break; + + case WEEKS: + calendarTime.add(Calendar.WEEK_OF_YEAR, -timeAgoAmount); + markApproximatedTime(calendarTime); + break; + + case MONTHS: + calendarTime.add(Calendar.MONTH, -timeAgoAmount); + markApproximatedTime(calendarTime); + break; + + case YEARS: + calendarTime.add(Calendar.YEAR, -timeAgoAmount); + // Prevent `PrettyTime` from showing '12 months ago'. + calendarTime.add(Calendar.DAY_OF_MONTH, -1); + markApproximatedTime(calendarTime); + break; + } + + return calendarTime; + } + + private Calendar getNow() { + return (Calendar) consistentNow.clone(); + } + + /** + * Marks the time as approximated by setting minutes, seconds and milliseconds to 0. + * @param calendarTime Time to be marked as approximated + */ + private void markApproximatedTime(Calendar calendarTime) { + calendarTime.set(Calendar.MINUTE, 0); + calendarTime.set(Calendar.SECOND, 0); + calendarTime.set(Calendar.MILLISECOND, 0); + } + + static { + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.SECONDS, Collections.singleton("sec")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MINUTES, Collections.singleton("min")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.HOURS, Collections.singleton("hour")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.DAYS, Collections.singleton("day")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.WEEKS, Collections.singleton("week")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MONTHS, Collections.singleton("month")); + DEFAULT_AGO_PHRASES.put(TimeAgoUnit.YEARS, Collections.singleton("year")); + } + + public enum TimeAgoUnit { + SECONDS, + MINUTES, + HOURS, + DAYS, + WEEKS, + MONTHS, + YEARS, + } +} diff --git a/extractor/src/test/java/org/schabi/newpipe/Downloader.java b/extractor/src/test/java/org/schabi/newpipe/Downloader.java index 3091c74bb..172b2ca78 100644 --- a/extractor/src/test/java/org/schabi/newpipe/Downloader.java +++ b/extractor/src/test/java/org/schabi/newpipe/Downloader.java @@ -41,6 +41,7 @@ import static java.util.Collections.singletonList; public class Downloader implements org.schabi.newpipe.extractor.Downloader { private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"; + private static final String DEFAULT_HTTP_ACCEPT_LANGUAGE = "en"; private static String mCookies = ""; private static Downloader instance = null; @@ -171,6 +172,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { URL url = new URL(siteUrl); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); // HttpsURLConnection con = NetCipher.getHttpsURLConnection(url); + con.setRequestProperty("Accept-Language", DEFAULT_HTTP_ACCEPT_LANGUAGE); return dl(con); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java index c2355a19f..3b839fd89 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java @@ -4,6 +4,7 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import java.util.Calendar; import java.util.List; import static org.junit.Assert.*; @@ -27,6 +28,14 @@ public final class DefaultTests { StreamInfoItem streamInfoItem = (StreamInfoItem) item; assertNotEmpty("Uploader name not set: " + item, streamInfoItem.getUploaderName()); assertNotEmpty("Uploader url not set: " + item, streamInfoItem.getUploaderUrl()); + + final String textualUploadDate = streamInfoItem.getTextualUploadDate(); + if (textualUploadDate != null && !textualUploadDate.isEmpty()) { + final Calendar uploadDate = streamInfoItem.getUploadDate(); + assertNotNull("No parsed upload date", uploadDate); + assertTrue("Upload date not in the past", uploadDate.before(Calendar.getInstance())); + } + } } } From 3638f0e0ea14d5e6ad84da95777da4181f8d32f7 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 28 Apr 2019 17:03:16 -0300 Subject: [PATCH 2/9] Implement time ago parser and improve localization handling - Handle special cases for languages where the number is not shown - Rework the Downloader base implementation, allowing for more advanced things to be done - Separate the localization from the content country (just like YouTube let's the user choose both). --- extractor/.attach_pid31246 | 0 .../newpipe/extractor/DownloadRequest.java | 44 --- .../newpipe/extractor/DownloadResponse.java | 42 --- .../schabi/newpipe/extractor/Downloader.java | 75 ----- .../schabi/newpipe/extractor/Extractor.java | 40 ++- .../newpipe/extractor/ListExtractor.java | 5 +- .../org/schabi/newpipe/extractor/NewPipe.java | 62 ++++- .../newpipe/extractor/StreamingService.java | 219 +++++++++------ .../extractor/SuggestionExtractor.java | 48 ---- .../extractor/channel/ChannelExtractor.java | 7 +- .../extractor/channel/ChannelInfo.java | 4 +- .../extractor/comments/CommentsExtractor.java | 9 +- .../extractor/comments/CommentsInfoItem.java | 121 ++++---- .../comments/CommentsInfoItemExtractor.java | 7 +- .../comments/CommentsInfoItemsCollector.java | 11 +- .../extractor/downloader/Downloader.java | 144 ++++++++++ .../newpipe/extractor/downloader/Request.java | 244 +++++++++++++++++ .../extractor/downloader/Response.java | 66 +++++ .../extractor/kiosk/KioskExtractor.java | 8 +- .../newpipe/extractor/kiosk/KioskInfo.java | 13 +- .../newpipe/extractor/kiosk/KioskList.java | 36 ++- .../localization/ContentCountry.java | 56 ++++ .../extractor/localization/Localization.java | 99 +++++++ .../TimeAgoParser.java | 98 ++++--- .../localization/TimeAgoPatternsManager.java | 25 ++ .../extractor/playlist/PlaylistExtractor.java | 5 +- .../extractor/playlist/PlaylistInfo.java | 1 - .../extractor/search/SearchExtractor.java | 10 +- .../newpipe/extractor/search/SearchInfo.java | 1 - .../services/media_ccc/MediaCCCService.java | 47 ++-- .../MediaCCCConferenceExtractor.java | 10 +- .../extractors/MediaCCCConferenceKiosk.java | 10 +- .../extractors/MediaCCCParsingHelper.java | 27 ++ .../extractors/MediaCCCSearchExtractor.java | 18 +- .../extractors/MediaCCCStreamExtractor.java | 25 +- .../MediaCCCSuggestionExtractor.java | 8 +- .../MediaCCCStreamInfoItemExtractor.java | 10 +- .../SoundcloudChannelExtractor.java | 11 +- .../soundcloud/SoundcloudChartsExtractor.java | 12 +- .../soundcloud/SoundcloudParsingHelper.java | 54 ++-- .../SoundcloudPlaylistExtractor.java | 11 +- .../soundcloud/SoundcloudSearchExtractor.java | 16 +- .../soundcloud/SoundcloudService.java | 53 ++-- .../soundcloud/SoundcloudStreamExtractor.java | 20 +- .../SoundcloudStreamInfoItemExtractor.java | 8 +- .../SoundcloudSuggestionExtractor.java | 12 +- .../services/youtube/YoutubeService.java | 119 ++++---- .../extractors/YoutubeChannelExtractor.java | 24 +- .../extractors/YoutubeCommentsExtractor.java | 61 ++--- .../YoutubeCommentsInfoItemExtractor.java | 30 +- .../extractors/YoutubePlaylistExtractor.java | 20 +- .../extractors/YoutubeSearchExtractor.java | 25 +- .../extractors/YoutubeStreamExtractor.java | 54 ++-- .../YoutubeStreamInfoItemExtractor.java | 2 +- .../YoutubeSuggestionExtractor.java | 14 +- .../extractors/YoutubeTrendingExtractor.java | 29 +- .../linkHandler/YoutubeParsingHelper.java | 23 +- .../extractor/stream/StreamExtractor.java | 36 ++- .../newpipe/extractor/stream/StreamInfo.java | 21 +- .../extractor/stream/StreamInfoItem.java | 7 +- .../stream/StreamInfoItemExtractor.java | 7 +- .../suggestion/SuggestionExtractor.java | 51 ++++ .../extractor/utils/DashMpdParser.java | 4 +- .../newpipe/extractor/utils/Localization.java | 19 -- .../java/org/schabi/newpipe/Downloader.java | 258 ------------------ .../schabi/newpipe/DownloaderTestImpl.java | 120 ++++++++ .../MediaCCCConferenceExtractorTest.java | 5 +- .../MediaCCCConferenceListExtractorTest.java | 9 +- .../services/media_ccc/MediaCCCOggTest.java | 6 +- .../MediaCCCSearchExtractorAllTest.java | 8 +- ...ediaCCCSearchExtractorConferencesTest.java | 8 +- .../MediaCCCSearchExtractorEventsTest.java | 8 +- .../MediaCCCStreamExtractorTest.java | 25 +- .../SoundcloudChannelExtractorTest.java | 7 +- .../SoundcloudChartsExtractorTest.java | 5 +- ...oundcloudChartsLinkHandlerFactoryTest.java | 5 +- .../SoundcloudParsingHelperTest.java | 7 +- .../SoundcloudPlaylistExtractorTest.java | 9 +- .../SoundcloudStreamExtractorDefaultTest.java | 20 +- ...oundcloudStreamLinkHandlerFactoryTest.java | 5 +- .../SoundcloudSubscriptionExtractorTest.java | 7 +- .../SoundcloudSuggestionExtractorTest.java | 7 +- ...ndcloudSearchExtractorChannelOnlyTest.java | 10 +- .../SoundcloudSearchExtractorDefaultTest.java | 10 +- .../search/SoundcloudSearchQHTest.java | 9 +- .../youtube/YoutubeChannelExtractorTest.java | 16 +- .../YoutubeChannelLinkHandlerFactoryTest.java | 5 +- .../YoutubeChannelLocalizationTest.java | 139 ++++++++++ .../youtube/YoutubeCommentsExtractorTest.java | 27 +- .../youtube/YoutubePlaylistExtractorTest.java | 7 +- ...YoutubePlaylistLinkHandlerFactoryTest.java | 5 +- .../services/youtube/YoutubeServiceTest.java | 5 +- .../YoutubeStreamLinkHandlerFactoryTest.java | 5 +- .../YoutubeSubscriptionExtractorTest.java | 5 +- .../YoutubeSuggestionExtractorTest.java | 8 +- .../youtube/YoutubeTrendingExtractorTest.java | 7 +- .../youtube/YoutubeTrendingKioskInfoTest.java | 7 +- ...YoutubeTrendingLinkHandlerFactoryTest.java | 5 +- .../search/YoutubeSearchCountTest.java | 7 +- ...YoutubeSearchExtractorChannelOnlyTest.java | 9 +- .../YoutubeSearchExtractorDefaultTest.java | 9 +- ...utubeStreamExtractorAgeRestrictedTest.java | 20 +- ...utubeStreamExtractorControversialTest.java | 19 +- .../YoutubeStreamExtractorDefaultTest.java | 27 +- .../YoutubeStreamExtractorLivestreamTest.java | 8 +- timeago-parser/build.gradle | 3 + .../raw/java/GeneratePatternClasses.java | 116 ++++++++ .../raw/java/GenerateResourceBundles.java | 59 ---- timeago-parser/raw/unique_patterns.json | 187 +++++++++++-- .../extractor/timeago/PatternsHolder.java | 99 +++++++ .../extractor/timeago/PatternsManager.java | 31 +++ .../extractor/timeago/ResourceBundleUTF8.java | 108 -------- .../timeago/TimeAgoPatternsManager.java | 24 -- .../extractor/timeago/TimeAgoUnit.java | 11 + .../extractor/timeago/patterns/af.java | 29 ++ .../extractor/timeago/patterns/am.java | 29 ++ .../extractor/timeago/patterns/ar.java | 29 ++ .../extractor/timeago/patterns/az.java | 29 ++ .../extractor/timeago/patterns/be.java | 29 ++ .../extractor/timeago/patterns/bg.java | 29 ++ .../extractor/timeago/patterns/bn.java | 29 ++ .../extractor/timeago/patterns/bs.java | 29 ++ .../extractor/timeago/patterns/ca.java | 29 ++ .../extractor/timeago/patterns/cs.java | 29 ++ .../extractor/timeago/patterns/da.java | 29 ++ .../extractor/timeago/patterns/de.java | 29 ++ .../extractor/timeago/patterns/el.java | 29 ++ .../extractor/timeago/patterns/en.java | 29 ++ .../extractor/timeago/patterns/en_GB.java | 29 ++ .../extractor/timeago/patterns/es.java | 29 ++ .../extractor/timeago/patterns/es_419.java | 29 ++ .../extractor/timeago/patterns/es_US.java | 29 ++ .../extractor/timeago/patterns/et.java | 29 ++ .../extractor/timeago/patterns/eu.java | 29 ++ .../extractor/timeago/patterns/fa.java | 29 ++ .../extractor/timeago/patterns/fi.java | 29 ++ .../extractor/timeago/patterns/fil.java | 29 ++ .../extractor/timeago/patterns/fr.java | 29 ++ .../extractor/timeago/patterns/fr_CA.java | 29 ++ .../extractor/timeago/patterns/gl.java | 29 ++ .../extractor/timeago/patterns/gu.java | 29 ++ .../extractor/timeago/patterns/hi.java | 29 ++ .../extractor/timeago/patterns/hr.java | 29 ++ .../extractor/timeago/patterns/hu.java | 29 ++ .../extractor/timeago/patterns/hy.java | 29 ++ .../extractor/timeago/patterns/id.java | 29 ++ .../extractor/timeago/patterns/is.java | 29 ++ .../extractor/timeago/patterns/it.java | 29 ++ .../extractor/timeago/patterns/iw.java | 35 +++ .../extractor/timeago/patterns/ja.java | 29 ++ .../extractor/timeago/patterns/ka.java | 29 ++ .../extractor/timeago/patterns/kk.java | 29 ++ .../extractor/timeago/patterns/km.java | 29 ++ .../extractor/timeago/patterns/kn.java | 29 ++ .../extractor/timeago/patterns/ko.java | 29 ++ .../extractor/timeago/patterns/ky.java | 29 ++ .../extractor/timeago/patterns/lo.java | 29 ++ .../extractor/timeago/patterns/lt.java | 29 ++ .../extractor/timeago/patterns/lv.java | 29 ++ .../extractor/timeago/patterns/mk.java | 29 ++ .../extractor/timeago/patterns/ml.java | 29 ++ .../extractor/timeago/patterns/mn.java | 29 ++ .../extractor/timeago/patterns/mr.java | 29 ++ .../extractor/timeago/patterns/ms.java | 29 ++ .../extractor/timeago/patterns/my.java | 29 ++ .../extractor/timeago/patterns/ne.java | 29 ++ .../extractor/timeago/patterns/nl.java | 29 ++ .../extractor/timeago/patterns/no.java | 29 ++ .../extractor/timeago/patterns/pa.java | 29 ++ .../extractor/timeago/patterns/pl.java | 29 ++ .../extractor/timeago/patterns/pt.java | 29 ++ .../extractor/timeago/patterns/pt_PT.java | 29 ++ .../extractor/timeago/patterns/ro.java | 29 ++ .../extractor/timeago/patterns/ru.java | 29 ++ .../extractor/timeago/patterns/si.java | 29 ++ .../extractor/timeago/patterns/sk.java | 29 ++ .../extractor/timeago/patterns/sl.java | 29 ++ .../extractor/timeago/patterns/sq.java | 29 ++ .../extractor/timeago/patterns/sr.java | 29 ++ .../extractor/timeago/patterns/sr_Latn.java | 29 ++ .../extractor/timeago/patterns/sv.java | 29 ++ .../extractor/timeago/patterns/sw.java | 29 ++ .../extractor/timeago/patterns/ta.java | 29 ++ .../extractor/timeago/patterns/te.java | 29 ++ .../extractor/timeago/patterns/th.java | 29 ++ .../extractor/timeago/patterns/tr.java | 29 ++ .../extractor/timeago/patterns/uk.java | 29 ++ .../extractor/timeago/patterns/ur.java | 29 ++ .../extractor/timeago/patterns/uz.java | 29 ++ .../extractor/timeago/patterns/vi.java | 29 ++ .../extractor/timeago/patterns/zh_CN.java | 29 ++ .../extractor/timeago/patterns/zh_HK.java | 29 ++ .../extractor/timeago/patterns/zh_TW.java | 29 ++ .../extractor/timeago/patterns/zu.java | 29 ++ .../resources/i18n/time_units_af.properties | 26 -- .../resources/i18n/time_units_am.properties | 27 -- .../resources/i18n/time_units_ar.properties | 35 --- .../resources/i18n/time_units_az.properties | 20 -- .../resources/i18n/time_units_be.properties | 28 -- .../resources/i18n/time_units_bg.properties | 27 -- .../resources/i18n/time_units_bn.properties | 20 -- .../resources/i18n/time_units_bs.properties | 27 -- .../resources/i18n/time_units_ca.properties | 27 -- .../resources/i18n/time_units_cs.properties | 27 -- .../resources/i18n/time_units_da.properties | 26 -- .../resources/i18n/time_units_de.properties | 27 -- .../resources/i18n/time_units_el.properties | 27 -- .../resources/i18n/time_units_en.properties | 27 -- .../i18n/time_units_en_GB.properties | 27 -- .../resources/i18n/time_units_es.properties | 27 -- .../i18n/time_units_es_419.properties | 27 -- .../i18n/time_units_es_US.properties | 27 -- .../resources/i18n/time_units_et.properties | 27 -- .../resources/i18n/time_units_eu.properties | 23 -- .../resources/i18n/time_units_fa.properties | 20 -- .../resources/i18n/time_units_fi.properties | 27 -- .../resources/i18n/time_units_fil.properties | 20 -- .../resources/i18n/time_units_fr.properties | 26 -- .../i18n/time_units_fr_CA.properties | 26 -- .../resources/i18n/time_units_gl.properties | 27 -- .../resources/i18n/time_units_gu.properties | 20 -- .../resources/i18n/time_units_hi.properties | 22 -- .../resources/i18n/time_units_hr.properties | 32 --- .../resources/i18n/time_units_hu.properties | 20 -- .../resources/i18n/time_units_hy.properties | 20 -- .../resources/i18n/time_units_id.properties | 20 -- .../resources/i18n/time_units_is.properties | 27 -- .../resources/i18n/time_units_it.properties | 27 -- .../resources/i18n/time_units_iw.properties | 27 -- .../resources/i18n/time_units_ja.properties | 20 -- .../resources/i18n/time_units_ka.properties | 20 -- .../resources/i18n/time_units_kk.properties | 20 -- .../resources/i18n/time_units_km.properties | 27 -- .../resources/i18n/time_units_kn.properties | 27 -- .../resources/i18n/time_units_ko.properties | 20 -- .../resources/i18n/time_units_ky.properties | 20 -- .../resources/i18n/time_units_lo.properties | 21 -- .../resources/i18n/time_units_lt.properties | 31 --- .../resources/i18n/time_units_lv.properties | 28 -- .../resources/i18n/time_units_mk.properties | 27 -- .../resources/i18n/time_units_ml.properties | 22 -- .../resources/i18n/time_units_mn.properties | 21 -- .../resources/i18n/time_units_mr.properties | 27 -- .../resources/i18n/time_units_ms.properties | 20 -- .../resources/i18n/time_units_my.properties | 20 -- .../resources/i18n/time_units_ne.properties | 20 -- .../resources/i18n/time_units_nl.properties | 25 -- .../resources/i18n/time_units_no.properties | 25 -- .../resources/i18n/time_units_pa.properties | 23 -- .../resources/i18n/time_units_pl.properties | 32 --- .../resources/i18n/time_units_pt.properties | 27 -- .../i18n/time_units_pt_PT.properties | 27 -- .../resources/i18n/time_units_ro.properties | 27 -- .../resources/i18n/time_units_ru.properties | 34 --- .../resources/i18n/time_units_si.properties | 20 -- .../resources/i18n/time_units_sk.properties | 27 -- .../resources/i18n/time_units_sl.properties | 34 --- .../resources/i18n/time_units_sq.properties | 23 -- .../resources/i18n/time_units_sr.properties | 29 -- .../i18n/time_units_sr_Latn.properties | 29 -- .../resources/i18n/time_units_sv.properties | 26 -- .../resources/i18n/time_units_sw.properties | 22 -- .../resources/i18n/time_units_ta.properties | 26 -- .../resources/i18n/time_units_te.properties | 27 -- .../resources/i18n/time_units_th.properties | 20 -- .../resources/i18n/time_units_tr.properties | 20 -- .../resources/i18n/time_units_uk.properties | 33 --- .../resources/i18n/time_units_ur.properties | 24 -- .../resources/i18n/time_units_uz.properties | 20 -- .../resources/i18n/time_units_vi.properties | 20 -- .../i18n/time_units_zh_CN.properties | 20 -- .../i18n/time_units_zh_HK.properties | 20 -- .../i18n/time_units_zh_TW.properties | 20 -- .../resources/i18n/time_units_zu.properties | 27 -- 274 files changed, 4770 insertions(+), 3468 deletions(-) delete mode 100644 extractor/.attach_pid31246 delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/DownloadRequest.java delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/DownloadResponse.java delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/Downloader.java delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/SuggestionExtractor.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Downloader.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Request.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Response.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/localization/ContentCountry.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java rename extractor/src/main/java/org/schabi/newpipe/extractor/{stream => localization}/TimeAgoParser.java (58%) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoPatternsManager.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/suggestion/SuggestionExtractor.java delete mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/utils/Localization.java delete mode 100644 extractor/src/test/java/org/schabi/newpipe/Downloader.java create mode 100644 extractor/src/test/java/org/schabi/newpipe/DownloaderTestImpl.java create mode 100644 extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java create mode 100644 timeago-parser/raw/java/GeneratePatternClasses.java delete mode 100644 timeago-parser/raw/java/GenerateResourceBundles.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsHolder.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsManager.java delete mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/ResourceBundleUTF8.java delete mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoPatternsManager.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoUnit.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/af.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/am.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ar.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/az.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/be.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bg.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bn.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bs.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ca.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/cs.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/da.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/de.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/el.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en_GB.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_419.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_US.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/et.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/eu.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fa.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fi.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fil.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr_CA.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gl.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gu.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hi.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hr.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hu.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hy.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/id.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/is.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/it.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/iw.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ja.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ka.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kk.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/km.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kn.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ko.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ky.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lo.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lt.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lv.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mk.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ml.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mn.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mr.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ms.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/my.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ne.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/nl.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/no.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pa.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pl.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt_PT.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ro.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ru.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/si.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sk.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sl.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sq.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr_Latn.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sv.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sw.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ta.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/te.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/th.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/tr.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uk.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ur.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uz.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/vi.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_CN.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_HK.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_TW.java create mode 100644 timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zu.java delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_af.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_am.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ar.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_az.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_be.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_bg.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_bn.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_bs.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ca.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_cs.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_da.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_de.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_el.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_en.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_en_GB.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_es.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_es_419.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_es_US.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_et.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_eu.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_fa.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_fi.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_fil.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_fr.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_fr_CA.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_gl.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_gu.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_hi.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_hr.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_hu.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_hy.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_id.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_is.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_it.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_iw.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ja.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ka.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_kk.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_km.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_kn.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ko.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ky.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_lo.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_lt.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_lv.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_mk.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ml.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_mn.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_mr.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ms.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_my.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ne.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_nl.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_no.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_pa.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_pl.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_pt.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_pt_PT.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ro.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ru.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_si.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sk.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sl.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sq.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sr.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sr_Latn.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sv.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_sw.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ta.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_te.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_th.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_tr.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_uk.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_ur.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_uz.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_vi.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_zh_CN.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_zh_HK.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_zh_TW.properties delete mode 100644 timeago-parser/src/main/resources/i18n/time_units_zu.properties diff --git a/extractor/.attach_pid31246 b/extractor/.attach_pid31246 deleted file mode 100644 index e69de29bb..000000000 diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadRequest.java b/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadRequest.java deleted file mode 100644 index 32c8a67fa..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadRequest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.schabi.newpipe.extractor; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public class DownloadRequest { - - private final String requestBody; - private final Map> requestHeaders; - public static final DownloadRequest emptyRequest = new DownloadRequest(null, null); - - public DownloadRequest(String requestBody, Map> headers) { - super(); - this.requestBody = requestBody; - if(null != headers) { - this.requestHeaders = headers; - }else { - this.requestHeaders = Collections.emptyMap(); - } - } - - public String getRequestBody() { - return requestBody; - } - - public Map> getRequestHeaders() { - return requestHeaders; - } - - public void setRequestCookies(List cookies){ - requestHeaders.put("Cookie", cookies); - } - - public List getRequestCookies(){ - if(null == requestHeaders) return Collections.emptyList(); - List cookies = requestHeaders.get("Cookie"); - if(null == cookies) - return Collections.emptyList(); - else - return cookies; - } - -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadResponse.java b/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadResponse.java deleted file mode 100644 index a2fc7e006..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/DownloadResponse.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.schabi.newpipe.extractor; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import javax.annotation.Nonnull; - -public class DownloadResponse { - private final int responseCode; - private final String responseBody; - private final Map> responseHeaders; - - public DownloadResponse(int responseCode, String responseBody, Map> headers) { - super(); - this.responseCode = responseCode; - this.responseBody = responseBody; - this.responseHeaders = headers; - } - - public int getResponseCode() { - return responseCode; - } - - public String getResponseBody() { - return responseBody; - } - - public Map> getResponseHeaders() { - return responseHeaders; - } - - @Nonnull - public List getResponseCookies(){ - if(null == responseHeaders) return Collections.emptyList(); - List cookies = responseHeaders.get("Set-Cookie"); - if(null == cookies) - return Collections.emptyList(); - else - return cookies; - } -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/Downloader.java b/extractor/src/main/java/org/schabi/newpipe/extractor/Downloader.java deleted file mode 100644 index f3526fcec..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/Downloader.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.schabi.newpipe.extractor; - -import java.io.IOException; -import java.util.Map; - -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; -import org.schabi.newpipe.extractor.utils.Localization; - -/* - * Created by Christian Schabesberger on 28.01.16. - * - * Copyright (C) Christian Schabesberger 2016 - * Downloader.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - -public interface Downloader { - - /** - * Download the text file at the supplied URL as in download(String), but set - * the HTTP header field "Accept-Language" to the supplied string. - * - * @param siteUrl the URL of the text file to return the contents of - * @param localization the language and country (usually a 2-character code for each) - * @return the contents of the specified text file - * @throws IOException - */ - String download(String siteUrl, Localization localization) throws IOException, ReCaptchaException; - - /** - * Download the text file at the supplied URL as in download(String), but set - * the HTTP header field "Accept-Language" to the supplied string. - * - * @param siteUrl the URL of the text file to return the contents of - * @param customProperties set request header properties - * @return the contents of the specified text file - * @throws IOException - */ - String download(String siteUrl, Map customProperties) throws IOException, ReCaptchaException; - - /** - * Download (via HTTP) the text file located at the supplied URL, and return its - * contents. Primarily intended for downloading web pages. - * - * @param siteUrl the URL of the text file to download - * @return the contents of the specified text file - * @throws IOException - */ - String download(String siteUrl) throws IOException, ReCaptchaException; - - DownloadResponse head(String siteUrl) throws IOException, ReCaptchaException; - - DownloadResponse get(String siteUrl, Localization localization) - throws IOException, ReCaptchaException; - - DownloadResponse get(String siteUrl, DownloadRequest request) - throws IOException, ReCaptchaException; - - DownloadResponse get(String siteUrl) throws IOException, ReCaptchaException; - - DownloadResponse post(String siteUrl, DownloadRequest request) - throws IOException, ReCaptchaException; -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/Extractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/Extractor.java index 055f7fd0d..e0fe4912c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/Extractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/Extractor.java @@ -1,9 +1,12 @@ package org.schabi.newpipe.extractor; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -16,21 +19,20 @@ public abstract class Extractor{ * Useful for getting other things from a service (like the url handlers for cleaning/accepting/get id from urls). */ private final StreamingService service; - private final LinkHandler linkHandler; - private final Localization localization; - @Nullable + @Nullable private Localization forcedLocalization = null; + @Nullable private ContentCountry forcedContentCountry = null; + private boolean pageFetched = false; private final Downloader downloader; - public Extractor(final StreamingService service, final LinkHandler linkHandler, final Localization localization) { + public Extractor(final StreamingService service, final LinkHandler linkHandler) { if(service == null) throw new NullPointerException("service is null"); if(linkHandler == null) throw new NullPointerException("LinkHandler is null"); this.service = service; this.linkHandler = linkHandler; this.downloader = NewPipe.getDownloader(); - this.localization = localization; if(downloader == null) throw new NullPointerException("downloader is null"); } @@ -105,8 +107,30 @@ public abstract class Extractor{ return downloader; } + /*////////////////////////////////////////////////////////////////////////// + // Localization + //////////////////////////////////////////////////////////////////////////*/ + + public void forceLocalization(Localization localization) { + this.forcedLocalization = localization; + } + + public void forceContentCountry(ContentCountry contentCountry) { + this.forcedContentCountry = contentCountry; + } + @Nonnull - public Localization getLocalization() { - return localization; + public Localization getExtractorLocalization() { + return forcedLocalization == null ? getService().getLocalization() : forcedLocalization; + } + + @Nonnull + public ContentCountry getExtractorContentCountry() { + return forcedContentCountry == null ? getService().getContentCountry() : forcedContentCountry; + } + + @Nonnull + public TimeAgoParser getTimeAgoParser() { + return getService().getTimeAgoParser(getExtractorLocalization()); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/ListExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/ListExtractor.java index ba3eb0a83..b254adbd8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/ListExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/ListExtractor.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.extractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; @@ -14,8 +13,8 @@ import java.util.List; */ public abstract class ListExtractor extends Extractor { - public ListExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public ListExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } /** diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/NewPipe.java b/extractor/src/main/java/org/schabi/newpipe/extractor/NewPipe.java index cf4a26437..fbb90a189 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/NewPipe.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/NewPipe.java @@ -20,24 +20,42 @@ package org.schabi.newpipe.extractor; * along with NewPipe. If not, see . */ +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.List; /** * Provides access to streaming services supported by NewPipe. */ public class NewPipe { - private static Downloader downloader = null; - private static Localization localization = null; + private static Downloader downloader; + private static Localization preferredLocalization; + private static ContentCountry preferredContentCountry; private NewPipe() { } + public static void init(Downloader d) { + downloader = d; + preferredLocalization = Localization.DEFAULT; + preferredContentCountry = ContentCountry.DEFAULT; + } + public static void init(Downloader d, Localization l) { downloader = d; - localization = l; + preferredLocalization = l; + preferredContentCountry = l.getCountryCode().isEmpty() ? ContentCountry.DEFAULT : new ContentCountry(l.getCountryCode()); + } + + public static void init(Downloader d, Localization l, ContentCountry c) { + downloader = d; + preferredLocalization = l; + preferredContentCountry = c; } public static Downloader getDownloader() { @@ -99,11 +117,41 @@ public class NewPipe { } } - public static void setLocalization(Localization localization) { - NewPipe.localization = localization; + /*////////////////////////////////////////////////////////////////////////// + // Localization + //////////////////////////////////////////////////////////////////////////*/ + + public static void setupLocalization(Localization preferredLocalization) { + setupLocalization(preferredLocalization, null); } + public static void setupLocalization(Localization preferredLocalization, @Nullable ContentCountry preferredContentCountry) { + NewPipe.preferredLocalization = preferredLocalization; + + if (preferredContentCountry != null) { + NewPipe.preferredContentCountry = preferredContentCountry; + } else { + NewPipe.preferredContentCountry = preferredLocalization.getCountryCode().isEmpty() + ? ContentCountry.DEFAULT + : new ContentCountry(preferredLocalization.getCountryCode()); + } + } + + @Nonnull public static Localization getPreferredLocalization() { - return localization; + return preferredLocalization == null ? Localization.DEFAULT : preferredLocalization; + } + + public static void setPreferredLocalization(Localization preferredLocalization) { + NewPipe.preferredLocalization = preferredLocalization; + } + + @Nonnull + public static ContentCountry getPreferredContentCountry() { + return preferredContentCountry == null ? ContentCountry.DEFAULT : preferredContentCountry; + } + + public static void setPreferredContentCountry(ContentCountry preferredContentCountry) { + NewPipe.preferredContentCountry = preferredContentCountry; } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java index c613d34f2..4906de9ef 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java @@ -1,25 +1,23 @@ package org.schabi.newpipe.extractor; -import java.util.Collections; -import java.util.List; - import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.kiosk.KioskList; -import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; +import org.schabi.newpipe.extractor.linkhandler.*; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; +import org.schabi.newpipe.extractor.localization.TimeAgoPatternsManager; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor; -import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; + +import java.util.Collections; +import java.util.List; /* * Copyright (C) Christian Schabesberger 2018 @@ -113,9 +111,9 @@ public abstract class StreamingService { return serviceId + ":" + serviceInfo.getName(); } - //////////////////////////////////////////// + /*////////////////////////////////////////////////////////////////////////// // Url Id handler - //////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////*/ /** * Must return a new instance of an implementation of LinkHandlerFactory for streams. @@ -144,25 +142,22 @@ public abstract class StreamingService { public abstract SearchQueryHandlerFactory getSearchQHFactory(); public abstract ListLinkHandlerFactory getCommentsLHFactory(); - - //////////////////////////////////////////// - // Extractor - //////////////////////////////////////////// + /*////////////////////////////////////////////////////////////////////////// + // Extractors + //////////////////////////////////////////////////////////////////////////*/ /** * Must create a new instance of a SearchExtractor implementation. * @param queryHandler specifies the keyword lock for, and the filters which should be applied. - * @param localization specifies the language/country for the extractor. * @return a new SearchExtractor instance */ - public abstract SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler, Localization localization); + public abstract SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler); /** * Must create a new instance of a SuggestionExtractor implementation. - * @param localization specifies the language/country for the extractor. * @return a new SuggestionExtractor instance */ - public abstract SuggestionExtractor getSuggestionExtractor(Localization localization); + public abstract SuggestionExtractor getSuggestionExtractor(); /** * Outdated or obsolete. null can be returned. @@ -180,113 +175,72 @@ public abstract class StreamingService { /** * Must create a new instance of a ChannelExtractor implementation. * @param linkHandler is pointing to the channel which should be handled by this new instance. - * @param localization specifies the language used for the request. * @return a new ChannelExtractor * @throws ExtractionException */ - public abstract ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler, - Localization localization) throws ExtractionException; + public abstract ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) throws ExtractionException; /** * Must crete a new instance of a PlaylistExtractor implementation. * @param linkHandler is pointing to the playlist which should be handled by this new instance. - * @param localization specifies the language used for the request. * @return a new PlaylistExtractor * @throws ExtractionException */ - public abstract PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler, - Localization localization) throws ExtractionException; + public abstract PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) throws ExtractionException; /** * Must create a new instance of a StreamExtractor implementation. * @param linkHandler is pointing to the stream which should be handled by this new instance. - * @param localization specifies the language used for the request. * @return a new StreamExtractor * @throws ExtractionException */ - public abstract StreamExtractor getStreamExtractor(LinkHandler linkHandler, - Localization localization) throws ExtractionException; - public abstract CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler, - Localization localization) throws ExtractionException; - //////////////////////////////////////////// - // Extractor with default localization - //////////////////////////////////////////// + public abstract StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException; - public SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler) { - return getSearchExtractor(queryHandler, NewPipe.getPreferredLocalization()); - } + public abstract CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler) throws ExtractionException; - public SuggestionExtractor getSuggestionExtractor() { - return getSuggestionExtractor(NewPipe.getPreferredLocalization()); - } - - public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) throws ExtractionException { - return getChannelExtractor(linkHandler, NewPipe.getPreferredLocalization()); - } - - public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) throws ExtractionException { - return getPlaylistExtractor(linkHandler, NewPipe.getPreferredLocalization()); - } - - public StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException { - return getStreamExtractor(linkHandler, NewPipe.getPreferredLocalization()); - } - - public CommentsExtractor getCommentsExtractor(ListLinkHandler urlIdHandler) throws ExtractionException { - return getCommentsExtractor(urlIdHandler, NewPipe.getPreferredLocalization()); - } - - //////////////////////////////////////////// - // Extractor without link handler - //////////////////////////////////////////// + /*////////////////////////////////////////////////////////////////////////// + // Extractors without link handler + //////////////////////////////////////////////////////////////////////////*/ public SearchExtractor getSearchExtractor(String query, List contentFilter, - String sortFilter, - Localization localization) throws ExtractionException { + String sortFilter) throws ExtractionException { return getSearchExtractor(getSearchQHFactory() - .fromQuery(query, - contentFilter, - sortFilter), - localization); + .fromQuery(query, contentFilter, sortFilter)); } public ChannelExtractor getChannelExtractor(String id, List contentFilter, - String sortFilter, - Localization localization) throws ExtractionException { - return getChannelExtractor(getChannelLHFactory().fromQuery(id, contentFilter, sortFilter), localization); + String sortFilter) throws ExtractionException { + return getChannelExtractor(getChannelLHFactory() + .fromQuery(id, contentFilter, sortFilter)); } public PlaylistExtractor getPlaylistExtractor(String id, List contentFilter, - String sortFilter, - Localization localization) throws ExtractionException { + String sortFilter) throws ExtractionException { return getPlaylistExtractor(getPlaylistLHFactory() - .fromQuery(id, - contentFilter, - sortFilter), - localization); + .fromQuery(id, contentFilter, sortFilter)); } - //////////////////////////////////////////// - // Short extractor without localization - //////////////////////////////////////////// + /*////////////////////////////////////////////////////////////////////////// + // Short extractors overloads + //////////////////////////////////////////////////////////////////////////*/ public SearchExtractor getSearchExtractor(String query) throws ExtractionException { - return getSearchExtractor(getSearchQHFactory().fromQuery(query), NewPipe.getPreferredLocalization()); + return getSearchExtractor(getSearchQHFactory().fromQuery(query)); } public ChannelExtractor getChannelExtractor(String url) throws ExtractionException { - return getChannelExtractor(getChannelLHFactory().fromUrl(url), NewPipe.getPreferredLocalization()); + return getChannelExtractor(getChannelLHFactory().fromUrl(url)); } public PlaylistExtractor getPlaylistExtractor(String url) throws ExtractionException { - return getPlaylistExtractor(getPlaylistLHFactory().fromUrl(url), NewPipe.getPreferredLocalization()); + return getPlaylistExtractor(getPlaylistLHFactory().fromUrl(url)); } public StreamExtractor getStreamExtractor(String url) throws ExtractionException { - return getStreamExtractor(getStreamLHFactory().fromUrl(url), NewPipe.getPreferredLocalization()); + return getStreamExtractor(getStreamLHFactory().fromUrl(url)); } public CommentsExtractor getCommentsExtractor(String url) throws ExtractionException { @@ -294,12 +248,12 @@ public abstract class StreamingService { if(null == llhf) { return null; } - return getCommentsExtractor(llhf.fromUrl(url), NewPipe.getPreferredLocalization()); + return getCommentsExtractor(llhf.fromUrl(url)); } - public TimeAgoParser getTimeAgoParser() { - return new TimeAgoParser(TimeAgoParser.DEFAULT_AGO_PHRASES); - } + /*////////////////////////////////////////////////////////////////////////// + // Utils + //////////////////////////////////////////////////////////////////////////*/ /** * Figures out where the link is pointing to (a channel, a video, a playlist, etc.) @@ -322,4 +276,95 @@ public abstract class StreamingService { return LinkType.NONE; } } + + /*////////////////////////////////////////////////////////////////////////// + // Localization + //////////////////////////////////////////////////////////////////////////*/ + + /** + * Returns a list of localizations that this service supports. + */ + public List getSupportedLocalizations() { + return Collections.singletonList(Localization.DEFAULT); + } + + /** + * Returns a list of countries that this service supports.
+ */ + public List getSupportedCountries() { + return Collections.singletonList(ContentCountry.DEFAULT); + } + + /** + * Returns the localization that should be used in this service. It will get which localization + * the user prefer (using {@link NewPipe#getPreferredLocalization()}), then it will: + *
    + *
  • Check if the exactly localization is supported by this service.
  • + *
  • If not, check if a less specific localization is available, using only the language code.
  • + *
  • Fallback to the {@link Localization#DEFAULT default} localization.
  • + *
+ */ + public Localization getLocalization() { + final Localization preferredLocalization = NewPipe.getPreferredLocalization(); + + // Check the localization's language and country + if (getSupportedLocalizations().contains(preferredLocalization)) { + return preferredLocalization; + } + + // Fallback to the first supported language that matches the preferred language + for (Localization supportedLanguage : getSupportedLocalizations()) { + if (supportedLanguage.getLanguageCode().equals(preferredLocalization.getLanguageCode())) { + return supportedLanguage; + } + } + + return Localization.DEFAULT; + } + + /** + * Returns the country that should be used to fetch content in this service. It will get which country + * the user prefer (using {@link NewPipe#getPreferredContentCountry()}), then it will: + *
    + *
  • Check if the country is supported by this service.
  • + *
  • If not, fallback to the {@link ContentCountry#DEFAULT default} country.
  • + *
+ */ + public ContentCountry getContentCountry() { + final ContentCountry preferredContentCountry = NewPipe.getPreferredContentCountry(); + + if (getSupportedCountries().contains(preferredContentCountry)) { + return preferredContentCountry; + } + + return ContentCountry.DEFAULT; + } + + /** + * Get an instance of the time ago parser using the patterns related to the passed localization.
+ *
+ * Just like {@link #getLocalization()}, it will also try to fallback to a less specific localization if + * the exact one is not available/supported. + * + * @throws IllegalArgumentException if the localization is not supported (parsing patterns are not present). + */ + public TimeAgoParser getTimeAgoParser(Localization localization) { + final TimeAgoParser targetParser = TimeAgoPatternsManager.getTimeAgoParserFor(localization); + + if (targetParser != null) { + return targetParser; + } + + if (!localization.getCountryCode().isEmpty()) { + final Localization lessSpecificLocalization = new Localization(localization.getLanguageCode()); + final TimeAgoParser lessSpecificParser = TimeAgoPatternsManager.getTimeAgoParserFor(lessSpecificLocalization); + + if (lessSpecificParser != null) { + return lessSpecificParser; + } + } + + throw new IllegalArgumentException("Localization is not supported (\"" + localization.toString() + "\")"); + } + } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/SuggestionExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/SuggestionExtractor.java deleted file mode 100644 index 10147ea16..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/SuggestionExtractor.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.schabi.newpipe.extractor; - -import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; - -import java.io.IOException; -import java.util.List; - -/* - * Created by Christian Schabesberger on 28.09.16. - * - * Copyright (C) Christian Schabesberger 2016 - * SuggestionExtractor.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - -public abstract class SuggestionExtractor { - - private final int serviceId; - private final Localization localization; - - public SuggestionExtractor(int serviceId, Localization localization) { - this.serviceId = serviceId; - this.localization = localization; - } - - public abstract List suggestionList(String query) throws IOException, ExtractionException; - - public int getServiceId() { - return serviceId; - } - - protected Localization getLocalization() { - return localization; - } -} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelExtractor.java index 5172e0977..6d529d6b6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelExtractor.java @@ -3,9 +3,8 @@ package org.schabi.newpipe.extractor.channel; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; /* * Created by Christian Schabesberger on 25.07.16. @@ -29,8 +28,8 @@ import org.schabi.newpipe.extractor.utils.Localization; public abstract class ChannelExtractor extends ListExtractor { - public ChannelExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public ChannelExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } public abstract String getAvatarUrl() throws ParsingException; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelInfo.java index 0832b601b..aaa99c7b7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/channel/ChannelInfo.java @@ -6,10 +6,10 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.utils.ExtractorHelper; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsExtractor.java index a396637c2..d1599affb 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsExtractor.java @@ -3,13 +3,12 @@ package org.schabi.newpipe.extractor.comments; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; public abstract class CommentsExtractor extends ListExtractor { - public CommentsExtractor(StreamingService service, ListLinkHandler uiHandler, Localization localization) { - super(service, uiHandler, localization); - // TODO Auto-generated constructor stub - } + public CommentsExtractor(StreamingService service, ListLinkHandler uiHandler) { + super(service, uiHandler); + // TODO Auto-generated constructor stub + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java index 87d54a0df..7e225026e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java @@ -2,75 +2,84 @@ package org.schabi.newpipe.extractor.comments; import org.schabi.newpipe.extractor.InfoItem; -public class CommentsInfoItem extends InfoItem{ +import java.util.Calendar; - private String commentId; - private String commentText; - private String authorName; - private String authorThumbnail; - private String authorEndpoint; - private String publishedTime; - private Integer likeCount; - - public CommentsInfoItem(int serviceId, String url, String name) { - super(InfoType.COMMENT, serviceId, url, name); - // TODO Auto-generated constructor stub - } - - public String getCommentText() { - return commentText; - } +public class CommentsInfoItem extends InfoItem { - public void setCommentText(String contentText) { - this.commentText = contentText; - } + private String commentId; + private String commentText; + private String authorName; + private String authorThumbnail; + private String authorEndpoint; + private String textualPublishedTime; + private Calendar publishedTime; + private int likeCount; - public String getAuthorName() { - return authorName; - } + public CommentsInfoItem(int serviceId, String url, String name) { + super(InfoType.COMMENT, serviceId, url, name); + } - public void setAuthorName(String authorName) { - this.authorName = authorName; - } + public String getCommentId() { + return commentId; + } - public String getAuthorThumbnail() { - return authorThumbnail; - } + public void setCommentId(String commentId) { + this.commentId = commentId; + } - public void setAuthorThumbnail(String authorThumbnail) { - this.authorThumbnail = authorThumbnail; - } + public String getCommentText() { + return commentText; + } - public String getAuthorEndpoint() { - return authorEndpoint; - } + public void setCommentText(String commentText) { + this.commentText = commentText; + } - public void setAuthorEndpoint(String authorEndpoint) { - this.authorEndpoint = authorEndpoint; - } + public String getAuthorName() { + return authorName; + } - public String getPublishedTime() { - return publishedTime; - } + public void setAuthorName(String authorName) { + this.authorName = authorName; + } - public void setPublishedTime(String publishedTime) { - this.publishedTime = publishedTime; - } + public String getAuthorThumbnail() { + return authorThumbnail; + } - public Integer getLikeCount() { - return likeCount; - } + public void setAuthorThumbnail(String authorThumbnail) { + this.authorThumbnail = authorThumbnail; + } - public void setLikeCount(Integer likeCount) { - this.likeCount = likeCount; - } + public String getAuthorEndpoint() { + return authorEndpoint; + } - public String getCommentId() { - return commentId; - } + public void setAuthorEndpoint(String authorEndpoint) { + this.authorEndpoint = authorEndpoint; + } - public void setCommentId(String commentId) { - this.commentId = commentId; - } + public String getTextualPublishedTime() { + return textualPublishedTime; + } + public void setTextualPublishedTime(String textualPublishedTime) { + this.textualPublishedTime = textualPublishedTime; + } + + public Calendar getPublishedTime() { + return publishedTime; + } + + public void setPublishedTime(Calendar publishedTime) { + this.publishedTime = publishedTime; + } + + public int getLikeCount() { + return likeCount; + } + + public void setLikeCount(int likeCount) { + this.likeCount = likeCount; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java index b9905c2a7..4560f0441 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java @@ -3,12 +3,15 @@ package org.schabi.newpipe.extractor.comments; import org.schabi.newpipe.extractor.InfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import java.util.Calendar; + public interface CommentsInfoItemExtractor extends InfoItemExtractor { String getCommentId() throws ParsingException; String getCommentText() throws ParsingException; String getAuthorName() throws ParsingException; String getAuthorThumbnail() throws ParsingException; String getAuthorEndpoint() throws ParsingException; - String getPublishedTime() throws ParsingException; - Integer getLikeCount() throws ParsingException; + String getTextualPublishedTime() throws ParsingException; + Calendar getPublishedTime() throws ParsingException; + int getLikeCount() throws ParsingException; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java index bf3bc3225..030d11181 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemsCollector.java @@ -1,12 +1,12 @@ package org.schabi.newpipe.extractor.comments; -import java.util.List; -import java.util.Vector; - import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItemsCollector; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import java.util.List; +import java.util.Vector; + public class CommentsInfoItemsCollector extends InfoItemsCollector { public CommentsInfoItemsCollector(int serviceId) { @@ -49,6 +49,11 @@ public class CommentsInfoItemsCollector extends InfoItemsCollector + *
+ * This method calls {@link #get(String, Map, Localization)} with the default preferred localization. It should only be + * used when the resource that will be fetched won't be affected by the localization. + * + * @param url the URL that is pointing to the wanted resource + * @return the result of the GET request + */ + public Response get(String url) throws IOException, ReCaptchaException { + return get(url, null, NewPipe.getPreferredLocalization()); + } + + /** + * Do a GET request to get the resource that the url is pointing to.
+ *
+ * It will set the {@code Accept-Language} header to the language of the localization parameter. + * + * @param url the URL that is pointing to the wanted resource + * @param localization the source of the value of the {@code Accept-Language} header + * @return the result of the GET request + */ + public Response get(String url, @Nullable Localization localization) throws IOException, ReCaptchaException { + return get(url, null, localization); + } + + /** + * Do a GET request with the specified headers. + * + * @param url the URL that is pointing to the wanted resource + * @param headers a list of headers that will be used in the request. + * Any default headers should be overridden by these. + * @return the result of the GET request + */ + public Response get(String url, @Nullable Map> headers) throws IOException, ReCaptchaException { + return get(url, headers, NewPipe.getPreferredLocalization()); + } + + /** + * Do a GET request with the specified headers.
+ *
+ * It will set the {@code Accept-Language} header to the language of the localization parameter. + * + * @param url the URL that is pointing to the wanted resource + * @param headers a list of headers that will be used in the request. + * Any default headers should be overridden by these. + * @param localization the source of the value of the {@code Accept-Language} header + * @return the result of the GET request + */ + public Response get(String url, @Nullable Map> headers, @Nullable Localization localization) + throws IOException, ReCaptchaException { + return execute(Request.newBuilder() + .get(url) + .headers(headers) + .localization(localization) + .build()); + } + + /** + * Do a HEAD request. + * + * @param url the URL that is pointing to the wanted resource + * @return the result of the HEAD request + */ + public Response head(String url) throws IOException, ReCaptchaException { + return head(url, null); + } + + /** + * Do a HEAD request with the specified headers. + * + * @param url the URL that is pointing to the wanted resource + * @param headers a list of headers that will be used in the request. + * Any default headers should be overridden by these. + * @return the result of the HEAD request + */ + public Response head(String url, @Nullable Map> headers) + throws IOException, ReCaptchaException { + return execute(Request.newBuilder() + .head(url) + .headers(headers) + .build()); + } + + /** + * Do a POST request with the specified headers, sending the data array. + * + * @param url the URL that is pointing to the wanted resource + * @param headers a list of headers that will be used in the request. + * Any default headers should be overridden by these. + * @param dataToSend byte array that will be sent when doing the request. + * @return the result of the GET request + */ + public Response post(String url, @Nullable Map> headers, @Nullable byte[] dataToSend) + throws IOException, ReCaptchaException { + return post(url, headers, dataToSend, NewPipe.getPreferredLocalization()); + } + + /** + * Do a POST request with the specified headers, sending the data array. + *
+ * It will set the {@code Accept-Language} header to the language of the localization parameter. + * + * @param url the URL that is pointing to the wanted resource + * @param headers a list of headers that will be used in the request. + * Any default headers should be overridden by these. + * @param dataToSend byte array that will be sent when doing the request. + * @param localization the source of the value of the {@code Accept-Language} header + * @return the result of the GET request + */ + public Response post(String url, @Nullable Map> headers, @Nullable byte[] dataToSend, @Nullable Localization localization) + throws IOException, ReCaptchaException { + return execute(Request.newBuilder() + .post(url, dataToSend) + .headers(headers) + .localization(localization) + .build()); + } + + /** + * Do a request using the specified {@link Request} object. + * + * @return the result of the request + */ + public abstract Response execute(@Nonnull Request request) throws IOException, ReCaptchaException; +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Request.java b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Request.java new file mode 100644 index 000000000..630bb59e4 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Request.java @@ -0,0 +1,244 @@ +package org.schabi.newpipe.extractor.downloader; + +import org.schabi.newpipe.extractor.localization.Localization; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + +/** + * An object that holds request information used when {@link Downloader#execute(Request) executing} a request. + */ +public class Request { + private final String httpMethod; + private final String url; + private final Map> headers; + @Nullable private final byte[] dataToSend; + @Nullable private final Localization localization; + + public Request(String httpMethod, String url, Map> headers, @Nullable byte[] dataToSend, + @Nullable Localization localization, boolean automaticLocalizationHeader) { + if (httpMethod == null) throw new IllegalArgumentException("Request's httpMethod is null"); + if (url == null) throw new IllegalArgumentException("Request's url is null"); + + this.httpMethod = httpMethod; + this.url = url; + this.dataToSend = dataToSend; + this.localization = localization; + + Map> headersToSet = null; + if (headers == null) headers = Collections.emptyMap(); + + if (automaticLocalizationHeader && localization != null) { + headersToSet = new LinkedHashMap<>(headersFromLocalization(localization)); + headersToSet.putAll(headers); + } + + this.headers = Collections.unmodifiableMap(headersToSet == null ? headers : headersToSet); + } + + private Request(Builder builder) { + this(builder.httpMethod, builder.url, builder.headers, builder.dataToSend, + builder.localization, builder.automaticLocalizationHeader); + } + + /** + * A http method (i.e. {@code GET, POST, HEAD}). + */ + public String httpMethod() { + return httpMethod; + } + + /** + * The URL that is pointing to the wanted resource. + */ + public String url() { + return url; + } + + /** + * A list of headers that will be used in the request.
+ * Any default headers that the implementation may have, should be overridden by these. + */ + public Map> headers() { + return headers; + } + + /** + * An optional byte array that will be sent when doing the request, very commonly used in + * {@code POST} requests.
+ *
+ * The implementation should make note of some recommended headers + * (for example, {@code Content-Length} in a post request). + */ + @Nullable + public byte[] dataToSend() { + return dataToSend; + } + + /** + * A localization object that should be used when executing a request.
+ *
+ * Usually the {@code Accept-Language} will be set to this value (a helper + * method to do this easily: {@link Request#headersFromLocalization(Localization)}). + */ + @Nullable + public Localization localization() { + return localization; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static final class Builder { + private String httpMethod; + private String url; + private Map> headers = new LinkedHashMap<>(); + private byte[] dataToSend; + private Localization localization; + private boolean automaticLocalizationHeader = true; + + public Builder() { + } + + /** + * A http method (i.e. {@code GET, POST, HEAD}). + */ + public Builder httpMethod(String httpMethod) { + this.httpMethod = httpMethod; + return this; + } + + /** + * The URL that is pointing to the wanted resource. + */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** + * A list of headers that will be used in the request.
+ * Any default headers that the implementation may have, should be overridden by these. + */ + public Builder headers(@Nullable Map> headers) { + if (headers == null) { + this.headers.clear(); + return this; + } + this.headers.clear(); + this.headers.putAll(headers); + return this; + } + + /** + * An optional byte array that will be sent when doing the request, very commonly used in + * {@code POST} requests.
+ *
+ * The implementation should make note of some recommended headers + * (for example, {@code Content-Length} in a post request). + */ + public Builder dataToSend(byte[] dataToSend) { + this.dataToSend = dataToSend; + return this; + } + + /** + * A localization object that should be used when executing a request.
+ *
+ * Usually the {@code Accept-Language} will be set to this value (a helper + * method to do this easily: {@link Request#headersFromLocalization(Localization)}). + */ + public Builder localization(Localization localization) { + this.localization = localization; + return this; + } + + /** + * If localization headers should automatically be included in the request. + */ + public Builder automaticLocalizationHeader(boolean automaticLocalizationHeader) { + this.automaticLocalizationHeader = automaticLocalizationHeader; + return this; + } + + + public Request build() { + return new Request(this); + } + + /*////////////////////////////////////////////////////////////////////////// + // Http Methods Utils + //////////////////////////////////////////////////////////////////////////*/ + + public Builder get(String url) { + this.httpMethod = "GET"; + this.url = url; + return this; + } + + public Builder head(String url) { + this.httpMethod = "HEAD"; + this.url = url; + return this; + } + + public Builder post(String url, @Nullable byte[] dataToSend) { + this.httpMethod = "POST"; + this.url = url; + this.dataToSend = dataToSend; + return this; + } + + /*////////////////////////////////////////////////////////////////////////// + // Additional Headers Utils + //////////////////////////////////////////////////////////////////////////*/ + + public Builder setHeaders(String headerName, List headerValueList) { + this.headers.remove(headerName); + this.headers.put(headerName, headerValueList); + return this; + } + + public Builder addHeaders(String headerName, List headerValueList) { + @Nullable List currentHeaderValueList = this.headers.get(headerName); + if (currentHeaderValueList == null) { + currentHeaderValueList = new ArrayList<>(); + } + + currentHeaderValueList.addAll(headerValueList); + this.headers.put(headerName, headerValueList); + return this; + } + + public Builder setHeader(String headerName, String headerValue) { + return setHeaders(headerName, Collections.singletonList(headerValue)); + } + + public Builder addHeader(String headerName, String headerValue) { + return addHeaders(headerName, Collections.singletonList(headerValue)); + } + + } + + /*////////////////////////////////////////////////////////////////////////// + // Utils + //////////////////////////////////////////////////////////////////////////*/ + + @SuppressWarnings("WeakerAccess") + @Nonnull + public static Map> headersFromLocalization(@Nullable Localization localization) { + if (localization == null) return Collections.emptyMap(); + + final Map> headers = new LinkedHashMap<>(); + if (!localization.getCountryCode().isEmpty()) { + headers.put("Accept-Language", Collections.singletonList(localization.getLocalizationCode() + + ", " + localization.getLanguageCode() + ";q=0.9")); + } else { + headers.put("Accept-Language", Collections.singletonList(localization.getLanguageCode())); + } + + return headers; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Response.java b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Response.java new file mode 100644 index 000000000..59c3911cc --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/downloader/Response.java @@ -0,0 +1,66 @@ +package org.schabi.newpipe.extractor.downloader; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * A Data class used to hold the results from requests made by the Downloader implementation. + */ +public class Response { + private final int responseCode; + private final String responseMessage; + private final Map> responseHeaders; + private final String responseBody; + + public Response(int responseCode, String responseMessage, Map> responseHeaders, @Nullable String responseBody) { + this.responseCode = responseCode; + this.responseMessage = responseMessage; + this.responseHeaders = responseHeaders != null ? responseHeaders : Collections.>emptyMap(); + + this.responseBody = responseBody == null ? "" : responseBody; + } + + public int responseCode() { + return responseCode; + } + + public String responseMessage() { + return responseMessage; + } + + public Map> responseHeaders() { + return responseHeaders; + } + + @Nonnull + public String responseBody() { + return responseBody; + } + + /*////////////////////////////////////////////////////////////////////////// + // Utils + //////////////////////////////////////////////////////////////////////////*/ + + /** + * For easy access to some header value that (usually) don't repeat itself. + *

For getting all the values associated to the header, use {@link #responseHeaders()} (e.g. {@code Set-Cookie}). + * + * @param name the name of the header + * @return the first value assigned to this header + */ + @Nullable + public String getHeader(String name) { + for (Map.Entry> headerEntry : responseHeaders.entrySet()) { + if (headerEntry.getKey().equalsIgnoreCase(name)) { + if (headerEntry.getValue().size() > 0) { + return headerEntry.getValue().get(0); + } + } + } + + return null; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskExtractor.java index e2786bbac..7aef494d3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskExtractor.java @@ -24,9 +24,8 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; import javax.annotation.Nonnull; @@ -35,9 +34,8 @@ public abstract class KioskExtractor extends ListExtractor. */ -import org.schabi.newpipe.extractor.*; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.ListInfo; +import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.utils.ExtractorHelper; import java.io.IOException; @@ -37,7 +40,8 @@ public class KioskInfo extends ListInfo { public static ListExtractor.InfoItemsPage getMoreItems(StreamingService service, String url, - String pageUrl) throws IOException, ExtractionException { + String pageUrl) + throws IOException, ExtractionException { KioskList kl = service.getKioskList(); KioskExtractor extractor = kl.getExtractorByUrl(url, pageUrl); return extractor.getPage(pageUrl); @@ -47,8 +51,7 @@ public class KioskInfo extends ListInfo { return getInfo(NewPipe.getServiceByUrl(url), url); } - public static KioskInfo getInfo(StreamingService service, - String url) throws IOException, ExtractionException { + public static KioskInfo getInfo(StreamingService service, String url) throws IOException, ExtractionException { KioskList kl = service.getKioskList(); KioskExtractor extractor = kl.getExtractorByUrl(url, null); extractor.fetchPage(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskList.java b/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskList.java index 3636110d7..4b20cfa9f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskList.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/kiosk/KioskList.java @@ -2,28 +2,33 @@ package org.schabi.newpipe.extractor.kiosk; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; +import javax.annotation.Nullable; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; public class KioskList { + public interface KioskExtractorFactory { KioskExtractor createNewKiosk(final StreamingService streamingService, final String url, - final String kioskId, - final Localization localization) + final String kioskId) throws ExtractionException, IOException; } - private final int service_id; + private final StreamingService service; private final HashMap kioskList = new HashMap<>(); private String defaultKiosk = null; + @Nullable private Localization forcedLocalization; + @Nullable private ContentCountry forcedContentCountry; + private class KioskEntry { public KioskEntry(KioskExtractorFactory ef, ListLinkHandlerFactory h) { extractorFactory = ef; @@ -33,8 +38,8 @@ public class KioskList { final ListLinkHandlerFactory handlerFactory; } - public KioskList(int service_id) { - this.service_id = service_id; + public KioskList(StreamingService service) { + this.service = service; } public void addKioskEntry(KioskExtractorFactory extractorFactory, ListLinkHandlerFactory handlerFactory, String id) @@ -89,8 +94,13 @@ public class KioskList { if(ke == null) { throw new ExtractionException("No kiosk found with the type: " + kioskId); } else { - return ke.extractorFactory.createNewKiosk(NewPipe.getService(service_id), - ke.handlerFactory.fromId(kioskId).getUrl(), kioskId, localization); + final KioskExtractor kioskExtractor = ke.extractorFactory.createNewKiosk(service, + ke.handlerFactory.fromId(kioskId).getUrl(), kioskId); + + if (forcedLocalization != null) kioskExtractor.forceLocalization(forcedLocalization); + if (forcedContentCountry != null) kioskExtractor.forceContentCountry(forcedContentCountry); + + return kioskExtractor; } } @@ -117,4 +127,12 @@ public class KioskList { public ListLinkHandlerFactory getListLinkHandlerFactoryByType(String type) { return kioskList.get(type).handlerFactory; } + + public void forceLocalization(@Nullable Localization localization) { + this.forcedLocalization = localization; + } + + public void forceContentCountry(@Nullable ContentCountry contentCountry) { + this.forcedContentCountry = contentCountry; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/ContentCountry.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/ContentCountry.java new file mode 100644 index 000000000..2398d9934 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/ContentCountry.java @@ -0,0 +1,56 @@ +package org.schabi.newpipe.extractor.localization; + +import javax.annotation.Nonnull; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Represents a country that should be used when fetching content. + *

+ * YouTube, for example, give different results in their feed depending on which country is selected. + *

+ */ +public class ContentCountry implements Serializable { + public static final ContentCountry DEFAULT = new ContentCountry(Localization.DEFAULT.getCountryCode()); + + @Nonnull private final String countryCode; + + public static List listFrom(String... countryCodeList) { + final List toReturn = new ArrayList<>(); + for (String countryCode : countryCodeList) { + toReturn.add(new ContentCountry(countryCode)); + } + return Collections.unmodifiableList(toReturn); + } + + public ContentCountry(@Nonnull String countryCode) { + this.countryCode = countryCode; + } + + @Nonnull + public String getCountryCode() { + return countryCode; + } + + @Override + public String toString() { + return getCountryCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ContentCountry)) return false; + + ContentCountry that = (ContentCountry) o; + + return countryCode.equals(that.countryCode); + } + + @Override + public int hashCode() { + return countryCode.hashCode(); + } +} 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 new file mode 100644 index 000000000..7461462ab --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java @@ -0,0 +1,99 @@ +package org.schabi.newpipe.extractor.localization; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.*; + +public class Localization implements Serializable { + public static final Localization DEFAULT = new Localization("en", "GB"); + + @Nonnull private final String languageCode; + @Nullable private final String countryCode; + + /** + * @param localizationCodeList a list of localization code, formatted like {@link #getLocalizationCode()} + */ + public static List listFrom(String... localizationCodeList) { + final List toReturn = new ArrayList<>(); + for (String localizationCode : localizationCodeList) { + toReturn.add(fromLocalizationCode(localizationCode)); + } + return Collections.unmodifiableList(toReturn); + } + + /** + * @param localizationCode a localization code, formatted like {@link #getLocalizationCode()} + */ + public static Localization fromLocalizationCode(String localizationCode) { + final int indexSeparator = localizationCode.indexOf("-"); + + final String languageCode, countryCode; + if (indexSeparator != -1) { + languageCode = localizationCode.substring(0, indexSeparator); + countryCode = localizationCode.substring(indexSeparator + 1); + } else { + languageCode = localizationCode; + countryCode = null; + } + + return new Localization(languageCode, countryCode); + } + + public Localization(@Nonnull String languageCode, @Nullable String countryCode) { + this.languageCode = languageCode; + this.countryCode = countryCode; + } + + public Localization(@Nonnull String languageCode) { + this(languageCode, null); + } + + public String getLanguageCode() { + return languageCode; + } + + @Nonnull + public String getCountryCode() { + return countryCode == null ? "" : countryCode; + } + + public Locale asLocale() { + return new Locale(getLanguageCode(), getCountryCode()); + } + + public static Localization fromLocale(@Nonnull Locale locale) { + return new Localization(locale.getLanguage(), locale.getCountry()); + } + + /** + * Return a formatted string in the form of: {@code language-Country}, or + * just {@code language} if country is {@code null}. + */ + public String getLocalizationCode() { + return languageCode + (countryCode == null ? "" : "-" + countryCode); + } + + @Override + public String toString() { + return "Localization[" + getLocalizationCode() + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Localization)) return false; + + Localization that = (Localization) o; + + if (!languageCode.equals(that.languageCode)) return false; + return countryCode != null ? countryCode.equals(that.countryCode) : that.countryCode == null; + } + + @Override + public int hashCode() { + int result = languageCode.hashCode(); + result = 31 * result + (countryCode != null ? countryCode.hashCode() : 0); + return result; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/TimeAgoParser.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java similarity index 58% rename from extractor/src/main/java/org/schabi/newpipe/extractor/stream/TimeAgoParser.java rename to extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java index e58e5576c..3d2e99237 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/TimeAgoParser.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java @@ -1,32 +1,21 @@ -package org.schabi.newpipe.extractor.stream; - -/* - * Created by wojcik.online on 2018-01-25. - */ +package org.schabi.newpipe.extractor.localization; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.timeago.PatternsHolder; +import org.schabi.newpipe.extractor.timeago.TimeAgoUnit; +import org.schabi.newpipe.extractor.utils.Parser; import java.util.Calendar; import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; import java.util.Map; +import java.util.regex.Pattern; /** * A helper class that is meant to be used by services that need to parse upload dates in the * format '2 days ago' or similar. */ public class TimeAgoParser { - - /** - * A set of english phrases that are contained in the time units. - * (e.g. '7 minutes ago' contains 'min') - */ - public static Map> DEFAULT_AGO_PHRASES = - new EnumMap<>(TimeAgoUnit.class); - - private final Map> agoPhrases; - + private final PatternsHolder patternsHolder; private final Calendar consistentNow; /** @@ -34,22 +23,35 @@ public class TimeAgoParser { *

* Instantiate a new {@link TimeAgoParser} every time you extract a new batch of items. *

- * @param agoPhrases A set of phrases how to recognize the time units in a given language. + * @param patternsHolder An object that holds the "time ago" patterns, special cases, and the language word separator. */ - public TimeAgoParser(Map> agoPhrases) { - this.agoPhrases = agoPhrases; + public TimeAgoParser(PatternsHolder patternsHolder) { + this.patternsHolder = patternsHolder; consistentNow = Calendar.getInstance(); } /** * Parses a textual date in the format '2 days ago' into a Calendar representation. - * Beginning with days ago, marks the date as approximated by setting minutes, seconds + * Beginning with weeks ago, marks the date as approximated by setting minutes, seconds * and milliseconds to 0. + * * @param textualDate The original date as provided by the streaming service * @return The parsed (approximated) time * @throws ParsingException if the time unit could not be recognized */ public Calendar parse(String textualDate) throws ParsingException { + for (Map.Entry> caseUnitEntry : patternsHolder.specialCases().entrySet()) { + final TimeAgoUnit timeAgoUnit = caseUnitEntry.getKey(); + for (Map.Entry caseMapToAmountEntry : caseUnitEntry.getValue().entrySet()) { + final String caseText = caseMapToAmountEntry.getKey(); + final Integer caseAmount = caseMapToAmountEntry.getValue(); + + if (textualDateMatches(textualDate, caseText)) { + return getCalendar(caseAmount, timeAgoUnit); + } + } + } + int timeAgoAmount; try { timeAgoAmount = parseTimeAgoAmount(textualDate); @@ -69,9 +71,11 @@ public class TimeAgoParser { } private TimeAgoUnit parseTimeAgoUnit(String textualDate) throws ParsingException { - for (TimeAgoUnit timeAgoUnit : agoPhrases.keySet()) { - for (String agoPhrase : agoPhrases.get(timeAgoUnit)) { - if (textualDate.toLowerCase().contains(agoPhrase.toLowerCase())){ + for (Map.Entry> entry : patternsHolder.asMap().entrySet()) { + final TimeAgoUnit timeAgoUnit = entry.getKey(); + + for (String agoPhrase : entry.getValue()) { + if (textualDateMatches(textualDate, agoPhrase)) { return timeAgoUnit; } } @@ -80,6 +84,32 @@ public class TimeAgoParser { throw new ParsingException("Unable to parse the date: " + textualDate); } + private boolean textualDateMatches(String textualDate, String agoPhrase) { + if (textualDate.equals(agoPhrase)) { + return true; + } + + if (patternsHolder.wordSeparator().isEmpty()) { + return textualDate.toLowerCase().contains(agoPhrase.toLowerCase()); + } else { + final String escapedPhrase = Pattern.quote(agoPhrase.toLowerCase()); + final String escapedSeparator; + if (patternsHolder.wordSeparator().equals(" ")) { + // From JDK8 → \h - Treat horizontal spaces as a normal one (non-breaking space, thin space, etc.) + escapedSeparator = "[ \\t\\xA0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000]"; + } else { + escapedSeparator = Pattern.quote(patternsHolder.wordSeparator()); + } + + // (^|separator)pattern($|separator) + // Check if the pattern is surrounded by separators or start/end of the string. + final String pattern = + "(^|" + escapedSeparator + ")" + escapedPhrase + "($|" + escapedSeparator + ")"; + + return Parser.isMatch(pattern, textualDate.toLowerCase()); + } + } + private Calendar getCalendar(int timeAgoAmount, TimeAgoUnit timeAgoUnit) { Calendar calendarTime = getNow(); @@ -135,24 +165,4 @@ public class TimeAgoParser { calendarTime.set(Calendar.SECOND, 0); calendarTime.set(Calendar.MILLISECOND, 0); } - - static { - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.SECONDS, Collections.singleton("sec")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MINUTES, Collections.singleton("min")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.HOURS, Collections.singleton("hour")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.DAYS, Collections.singleton("day")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.WEEKS, Collections.singleton("week")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MONTHS, Collections.singleton("month")); - DEFAULT_AGO_PHRASES.put(TimeAgoUnit.YEARS, Collections.singleton("year")); - } - - public enum TimeAgoUnit { - SECONDS, - MINUTES, - HOURS, - DAYS, - WEEKS, - MONTHS, - YEARS, - } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoPatternsManager.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoPatternsManager.java new file mode 100644 index 000000000..1b41addeb --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoPatternsManager.java @@ -0,0 +1,25 @@ +package org.schabi.newpipe.extractor.localization; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; +import org.schabi.newpipe.extractor.timeago.PatternsManager; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TimeAgoPatternsManager { + @Nullable + private static PatternsHolder getPatternsFor(@Nonnull Localization localization) { + return PatternsManager.getPatterns(localization.getLanguageCode(), localization.getCountryCode()); + } + + @Nullable + public static TimeAgoParser getTimeAgoParserFor(@Nonnull Localization localization) { + final PatternsHolder holder = getPatternsFor(localization); + + if (holder == null) { + return null; + } + + return new TimeAgoParser(holder); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistExtractor.java index cc3ae94c3..2a901dbf0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistExtractor.java @@ -5,12 +5,11 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; public abstract class PlaylistExtractor extends ListExtractor { - public PlaylistExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public PlaylistExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } public abstract String getThumbnailUrl() throws ParsingException; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistInfo.java index 978fdcdb4..87fcb947f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/playlist/PlaylistInfo.java @@ -9,7 +9,6 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.utils.ExtractorHelper; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchExtractor.java index fce602a90..0acc640e6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchExtractor.java @@ -6,7 +6,8 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.utils.Localization; + +import javax.annotation.Nonnull; public abstract class SearchExtractor extends ListExtractor { @@ -18,10 +19,8 @@ public abstract class SearchExtractor extends ListExtractor { private final InfoItemsSearchCollector collector; - public SearchExtractor(StreamingService service, - SearchQueryHandler linkHandler, - Localization localization) { - super(service, linkHandler, localization); + public SearchExtractor(StreamingService service, SearchQueryHandler linkHandler) { + super(service, linkHandler); collector = new InfoItemsSearchCollector(service.getServiceId()); } @@ -40,6 +39,7 @@ public abstract class SearchExtractor extends ListExtractor { return (SearchQueryHandler) super.getLinkHandler(); } + @Nonnull @Override public String getName() { return getLinkHandler().getSearchString(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchInfo.java index 6362b6c65..eedce719e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/search/SearchInfo.java @@ -7,7 +7,6 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; import org.schabi.newpipe.extractor.utils.ExtractorHelper; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java index a23295a97..7e7fa842d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCService.java @@ -1,24 +1,12 @@ package org.schabi.newpipe.extractor.services.media_ccc; -import static java.util.Arrays.asList; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; - -import java.io.IOException; - import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.SuggestionExtractor; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.kiosk.KioskList; -import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; +import org.schabi.newpipe.extractor.linkhandler.*; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceExtractor; @@ -31,7 +19,13 @@ import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearc import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCStreamLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; + +import java.io.IOException; + +import static java.util.Arrays.asList; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; public class MediaCCCService extends StreamingService { public MediaCCCService(int id) { @@ -39,8 +33,8 @@ public class MediaCCCService extends StreamingService { } @Override - public SearchExtractor getSearchExtractor(SearchQueryHandler query, Localization localization) { - return new MediaCCCSearchExtractor(this, query, localization); + public SearchExtractor getSearchExtractor(SearchQueryHandler query) { + return new MediaCCCSearchExtractor(this, query); } @Override @@ -64,28 +58,28 @@ public class MediaCCCService extends StreamingService { } @Override - public StreamExtractor getStreamExtractor(LinkHandler linkHandler, Localization localization) { - return new MediaCCCStreamExtractor(this, linkHandler, localization); + public StreamExtractor getStreamExtractor(LinkHandler linkHandler) { + return new MediaCCCStreamExtractor(this, linkHandler); } @Override - public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler, Localization localization) { - return new MediaCCCConferenceExtractor(this, linkHandler, localization); + public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) { + return new MediaCCCConferenceExtractor(this, linkHandler); } @Override - public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler, Localization localization) { + public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) { return null; } @Override - public SuggestionExtractor getSuggestionExtractor(Localization localization) { + public SuggestionExtractor getSuggestionExtractor() { return null; } @Override public KioskList getKioskList() throws ExtractionException { - KioskList list = new KioskList(getServiceId()); + KioskList list = new KioskList(this); // add kiosks here e.g.: try { @@ -93,10 +87,9 @@ public class MediaCCCService extends StreamingService { @Override public KioskExtractor createNewKiosk(StreamingService streamingService, String url, - String kioskId, - Localization localization) throws ExtractionException, IOException { + String kioskId) throws ExtractionException, IOException { return new MediaCCCConferenceKiosk(MediaCCCService.this, - new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId, localization); + new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId); } }, new MediaCCCConferencesListLinkHandlerFactory(), "conferences"); list.setDefaultKiosk("conferences"); @@ -118,7 +111,7 @@ public class MediaCCCService extends StreamingService { } @Override - public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler, Localization localization) + public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler) throws ExtractionException { return null; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java index faa4b444c..3ec206b30 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceExtractor.java @@ -4,16 +4,15 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCStreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; @@ -22,8 +21,8 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { private JsonObject conferenceData; - public MediaCCCConferenceExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public MediaCCCConferenceExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } @Override @@ -75,7 +74,7 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { try { - conferenceData = JsonParser.object().from(downloader.download(getUrl())); + conferenceData = JsonParser.object().from(downloader.get(getUrl()).responseBody()); } catch (JsonParserException jpe) { throw new ExtractionException("Could not parse json returnd by url: " + getUrl()); } @@ -87,6 +86,7 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor { return conferenceData.getString("title"); } + @Nonnull @Override public String getOriginalUrl() throws ParsingException { return "https://media.ccc.de/c/" + conferenceData.getString("acronym"); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceKiosk.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceKiosk.java index 7eac10c11..580f79b05 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceKiosk.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCConferenceKiosk.java @@ -4,16 +4,15 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItemsCollector; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCConferenceInfoItemExtractor; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; @@ -24,9 +23,8 @@ public class MediaCCCConferenceKiosk extends KioskExtractor { public MediaCCCConferenceKiosk(StreamingService streamingService, ListLinkHandler linkHandler, - String kioskId, - Localization localization) { - super(streamingService, linkHandler, kioskId, localization); + String kioskId) { + super(streamingService, linkHandler, kioskId); } @Nonnull @@ -53,7 +51,7 @@ public class MediaCCCConferenceKiosk extends KioskExtractor { @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { - String site = downloader.download(getLinkHandler().getUrl()); + String site = downloader.get(getLinkHandler().getUrl(), getExtractorLocalization()).responseBody(); try { doc = JsonParser.object().from(site); } catch (JsonParserException jpe) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java new file mode 100644 index 000000000..0a51af2aa --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCParsingHelper.java @@ -0,0 +1,27 @@ +package org.schabi.newpipe.extractor.services.media_ccc.extractors; + +import org.schabi.newpipe.extractor.exceptions.ParsingException; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public class MediaCCCParsingHelper { + private MediaCCCParsingHelper() { + } + + public static Calendar parseDateFrom(String textualUploadDate) throws ParsingException { + Date date; + try { + date = new SimpleDateFormat("yyyy-MM-dd").parse(textualUploadDate); + } catch (ParseException e) { + throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"", e); + } + + final Calendar uploadDate = Calendar.getInstance(); + uploadDate.setTime(date); + return uploadDate; + } + +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java index af6724b62..eab97ce32 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSearchExtractor.java @@ -4,11 +4,11 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; @@ -16,26 +16,24 @@ import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCStreamInfoItemExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; -import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.CONFERENCES; -import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.EVENTS; -import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.ALL; + import javax.annotation.Nonnull; import java.io.IOException; import java.util.List; +import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.*; + public class MediaCCCSearchExtractor extends SearchExtractor { private JsonObject doc; private MediaCCCConferenceKiosk conferenceKiosk; - public MediaCCCSearchExtractor(StreamingService service, SearchQueryHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public MediaCCCSearchExtractor(StreamingService service, SearchQueryHandler linkHandler) { + super(service, linkHandler); try { conferenceKiosk = new MediaCCCConferenceKiosk(service, new MediaCCCConferencesListLinkHandlerFactory().fromId("conferences"), - "conferences", - localization); + "conferences"); } catch (Exception e) { e.printStackTrace(); } @@ -88,7 +86,7 @@ public class MediaCCCSearchExtractor extends SearchExtractor { || getLinkHandler().getContentFilters().isEmpty()) { final String site; final String url = getUrl(); - site = downloader.download(url, getLocalization()); + site = downloader.get(url, getExtractorLocalization()).responseBody(); try { doc = JsonParser.object().from(site); } catch (JsonParserException jpe) { 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 616a3b865..16e5e0d52 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 @@ -4,19 +4,21 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.extractor.stream.*; -import org.schabi.newpipe.extractor.utils.Localization; -import org.schabi.newpipe.extractor.utils.Parser; import javax.annotation.Nonnull; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; public class MediaCCCStreamExtractor extends StreamExtractor { @@ -24,16 +26,22 @@ public class MediaCCCStreamExtractor extends StreamExtractor { private JsonObject data; private JsonObject conferenceData; - public MediaCCCStreamExtractor(StreamingService service, LinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public MediaCCCStreamExtractor(StreamingService service, LinkHandler linkHandler) { + super(service, linkHandler); } @Nonnull @Override - public String getUploadDate() throws ParsingException { + public String getTextualUploadDate() throws ParsingException { return data.getString("release_date"); } + @Nonnull + @Override + public Calendar getUploadDate() throws ParsingException { + return MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate()); + } + @Nonnull @Override public String getThumbnailUrl() throws ParsingException { @@ -200,9 +208,9 @@ public class MediaCCCStreamExtractor extends StreamExtractor { public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { try { data = JsonParser.object().from( - downloader.download(getLinkHandler().getUrl())); + downloader.get(getLinkHandler().getUrl()).responseBody()); conferenceData = JsonParser.object() - .from(downloader.download(getUploaderUrl())); + .from(downloader.get(getUploaderUrl()).responseBody()); } catch (JsonParserException jpe) { throw new ExtractionException("Could not parse json returned by url: " + getLinkHandler().getUrl(), jpe); } @@ -215,6 +223,7 @@ public class MediaCCCStreamExtractor extends StreamExtractor { return data.getString("title"); } + @Nonnull @Override public String getOriginalUrl() throws ParsingException { return data.getString("frontend_link"); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSuggestionExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSuggestionExtractor.java index 9c6b4742d..b84230758 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSuggestionExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCSuggestionExtractor.java @@ -1,8 +1,8 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors; -import org.schabi.newpipe.extractor.SuggestionExtractor; +import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; import java.io.IOException; import java.util.ArrayList; @@ -10,8 +10,8 @@ import java.util.List; public class MediaCCCSuggestionExtractor extends SuggestionExtractor { - public MediaCCCSuggestionExtractor(int serviceId, Localization localization) { - super(serviceId, localization); + public MediaCCCSuggestionExtractor(StreamingService service) { + super(service); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java index 99bd45adb..085c115b8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java @@ -2,9 +2,12 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems; import com.grack.nanojson.JsonObject; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; +import java.util.Calendar; + public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor { JsonObject event; @@ -45,10 +48,15 @@ public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor } @Override - public String getUploadDate() throws ParsingException { + public String getTextualUploadDate() throws ParsingException { return event.getString("release_date"); } + @Override + public Calendar getUploadDate() throws ParsingException { + return MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate()); + } + @Override public String getName() throws ParsingException { return event.getString("title"); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractor.java index 1942a04d1..545412173 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractor.java @@ -4,15 +4,14 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; @@ -25,8 +24,8 @@ public class SoundcloudChannelExtractor extends ChannelExtractor { private StreamInfoItemsCollector streamInfoItemsCollector = null; private String nextPageUrl = null; - public SoundcloudChannelExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public SoundcloudChannelExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } @Override @@ -36,7 +35,7 @@ public class SoundcloudChannelExtractor extends ChannelExtractor { String apiUrl = "https://api-v2.soundcloud.com/users/" + userId + "?client_id=" + SoundcloudParsingHelper.clientId(); - String response = downloader.download(apiUrl); + String response = downloader.get(apiUrl, getExtractorLocalization()).responseBody(); try { user = JsonParser.object().from(response); } catch (JsonParserException e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractor.java index 1a02166e4..b773a935e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractor.java @@ -1,18 +1,15 @@ package org.schabi.newpipe.extractor.services.soundcloud; -import org.schabi.newpipe.extractor.Downloader; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; -import java.util.Arrays; -import java.util.List; public class SoundcloudChartsExtractor extends KioskExtractor { private StreamInfoItemsCollector collector = null; @@ -20,9 +17,8 @@ public class SoundcloudChartsExtractor extends KioskExtractor { public SoundcloudChartsExtractor(StreamingService service, ListLinkHandler linkHandler, - String kioskId, - Localization localization) { - super(service, linkHandler, kioskId, localization); + String kioskId) { + super(service, linkHandler, kioskId); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java index d4a8123c0..56f59bfaa 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java @@ -8,10 +8,10 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfoItemsCollector; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; @@ -24,10 +24,10 @@ import java.io.IOException; import java.net.URLEncoder; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; +import java.util.*; +import static java.util.Collections.singletonList; +import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps; public class SoundcloudParsingHelper { @@ -46,23 +46,23 @@ public class SoundcloudParsingHelper { return clientId; } - final DownloadResponse download = dl.get("https://soundcloud.com"); - String response = download.getResponseBody(); + final Response download = dl.get("https://soundcloud.com"); + final String responseBody = download.responseBody(); final String clientIdPattern = ",client_id:\"(.*?)\""; - Document doc = Jsoup.parse(response); + Document doc = Jsoup.parse(responseBody); final Elements possibleScripts = doc.select("script[src*=\"sndcdn.com/assets/\"][src$=\".js\"]"); // The one containing the client id will likely be the last one Collections.reverse(possibleScripts); - final HashMap headers = new HashMap<>(); - headers.put("Range", "bytes=0-16384"); + final HashMap> headers = new HashMap<>(); + headers.put("Range", singletonList("bytes=0-16384")); for (Element element : possibleScripts) { final String srcUrl = element.attr("src"); if (srcUrl != null && !srcUrl.isEmpty()) { try { - return clientId = Parser.matchGroup1(clientIdPattern, dl.download(srcUrl, headers)); + return clientId = Parser.matchGroup1(clientIdPattern, dl.get(srcUrl, headers).responseBody()); } catch (RegexException ignored) { // Ignore it and proceed to try searching other script } @@ -76,23 +76,24 @@ public class SoundcloudParsingHelper { static boolean checkIfHardcodedClientIdIsValid(Downloader dl) throws IOException, ReCaptchaException { final String apiUrl = "https://api.soundcloud.com/connect?client_id=" + HARDCODED_CLIENT_ID; // Should return 200 to indicate that the client id is valid, a 401 is returned otherwise. - return dl.head(apiUrl).getResponseCode() == 200; + return dl.head(apiUrl).responseCode() == 200; } - static Date parseDate(String time) throws ParsingException { + static Calendar parseDate(String textualUploadDate) throws ParsingException { + Date date; try { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(time); + date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(textualUploadDate); } catch (ParseException e1) { try { - return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(time); + date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(textualUploadDate); } catch (ParseException e2) { - throw new ParsingException(e1.getMessage(), e2); + throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"" + ", " + e1.getMessage(), e2); } } - } - static String toTextualDate(String time) throws ParsingException { - return new SimpleDateFormat("yyyy-MM-dd").format(parseDate(time)); + final Calendar uploadDate = Calendar.getInstance(); + uploadDate.setTime(date); + return uploadDate; } /** @@ -106,7 +107,8 @@ public class SoundcloudParsingHelper { + "&client_id=" + clientId(); try { - return JsonParser.object().from(downloader.download(apiUrl)); + final String response = downloader.get(apiUrl, SoundCloud.getLocalization()).responseBody(); + return JsonParser.object().from(response); } catch (JsonParserException e) { throw new ParsingException("Could not parse json response", e); } @@ -119,8 +121,8 @@ public class SoundcloudParsingHelper { */ public static String resolveUrlWithEmbedPlayer(String apiUrl) throws IOException, ReCaptchaException, ParsingException { - String response = NewPipe.getDownloader().download("https://w.soundcloud.com/player/?url=" - + URLEncoder.encode(apiUrl, "UTF-8")); + String response = NewPipe.getDownloader().get("https://w.soundcloud.com/player/?url=" + + URLEncoder.encode(apiUrl, "UTF-8"), SoundCloud.getLocalization()).responseBody(); return Jsoup.parse(response).select("link[rel=\"canonical\"]").first().attr("abs:href"); } @@ -132,8 +134,8 @@ public class SoundcloudParsingHelper { */ public static String resolveIdWithEmbedPlayer(String url) throws IOException, ReCaptchaException, ParsingException { - String response = NewPipe.getDownloader().download("https://w.soundcloud.com/player/?url=" - + URLEncoder.encode(url, "UTF-8")); + String response = NewPipe.getDownloader().get("https://w.soundcloud.com/player/?url=" + + URLEncoder.encode(url, "UTF-8"), SoundCloud.getLocalization()).responseBody(); // handle playlists / sets different and get playlist id via uir field in JSON if (url.contains("sets") && !url.endsWith("sets") && !url.endsWith("sets/")) return Parser.matchGroup1("\"uri\":\\s*\"https:\\/\\/api\\.soundcloud\\.com\\/playlists\\/((\\d)*?)\"", response); @@ -164,7 +166,7 @@ public class SoundcloudParsingHelper { * @return the next streams url, empty if don't have */ public static String getUsersFromApi(ChannelInfoItemsCollector collector, String apiUrl) throws IOException, ReCaptchaException, ParsingException { - String response = NewPipe.getDownloader().download(apiUrl); + String response = NewPipe.getDownloader().get(apiUrl, SoundCloud.getLocalization()).responseBody(); JsonObject responseObject; try { responseObject = JsonParser.object().from(response); @@ -215,7 +217,7 @@ public class SoundcloudParsingHelper { * @return the next streams url, empty if don't have */ public static String getStreamsFromApi(StreamInfoItemsCollector collector, String apiUrl, boolean charts) throws IOException, ReCaptchaException, ParsingException { - String response = NewPipe.getDownloader().download(apiUrl); + String response = NewPipe.getDownloader().get(apiUrl, SoundCloud.getLocalization()).responseBody(); JsonObject responseObject; try { responseObject = JsonParser.object().from(response); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractor.java index 2c27fa91d..5bc309724 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractor.java @@ -3,15 +3,14 @@ package org.schabi.newpipe.extractor.services.soundcloud; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; import java.io.IOException; @@ -24,8 +23,8 @@ public class SoundcloudPlaylistExtractor extends PlaylistExtractor { private StreamInfoItemsCollector streamInfoItemsCollector = null; private String nextPageUrl = null; - public SoundcloudPlaylistExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public SoundcloudPlaylistExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } @Override @@ -36,7 +35,7 @@ public class SoundcloudPlaylistExtractor extends PlaylistExtractor { "?client_id=" + SoundcloudParsingHelper.clientId() + "&representation=compact"; - String response = downloader.download(apiUrl); + String response = downloader.get(apiUrl, getExtractorLocalization()).responseBody(); try { playlist = JsonParser.object().from(response); } catch (JsonParserException e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSearchExtractor.java index 65d32ad29..97e69dc6f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSearchExtractor.java @@ -5,12 +5,12 @@ import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; import org.schabi.newpipe.extractor.*; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector; import org.schabi.newpipe.extractor.search.SearchExtractor; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Parser; import javax.annotation.Nonnull; @@ -25,10 +25,8 @@ public class SoundcloudSearchExtractor extends SearchExtractor { private JsonArray searchCollection; - public SoundcloudSearchExtractor(StreamingService service, - SearchQueryHandler linkHandler, - Localization localization) { - super(service, linkHandler, localization); + public SoundcloudSearchExtractor(StreamingService service, SearchQueryHandler linkHandler) { + super(service, linkHandler); } @Override @@ -51,7 +49,8 @@ public class SoundcloudSearchExtractor extends SearchExtractor { public InfoItemsPage getPage(String pageUrl) throws IOException, ExtractionException { final Downloader dl = getDownloader(); try { - searchCollection = JsonParser.object().from(dl.download(pageUrl)).getArray("collection"); + final String response = dl.get(pageUrl, getExtractorLocalization()).responseBody(); + searchCollection = JsonParser.object().from(response).getArray("collection"); } catch (JsonParserException e) { throw new ParsingException("Could not parse json response", e); } @@ -64,7 +63,8 @@ public class SoundcloudSearchExtractor extends SearchExtractor { final Downloader dl = getDownloader(); final String url = getUrl(); try { - searchCollection = JsonParser.object().from(dl.download(url)).getArray("collection"); + final String response = dl.get(url, getExtractorLocalization()).responseBody(); + searchCollection = JsonParser.object().from(response).getArray("collection"); } catch (JsonParserException e) { throw new ParsingException("Could not parse json response", e); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java index d2387d3c2..b480baff8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java @@ -1,26 +1,19 @@ package org.schabi.newpipe.extractor.services.soundcloud; -import static java.util.Collections.singletonList; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; - import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.SuggestionExtractor; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.kiosk.KioskList; -import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; +import org.schabi.newpipe.extractor.linkhandler.*; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.extractor.utils.Localization; + +import static java.util.Collections.singletonList; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; public class SoundcloudService extends StreamingService { @@ -28,11 +21,6 @@ public class SoundcloudService extends StreamingService { super(id, "SoundCloud", singletonList(AUDIO)); } - @Override - public SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler, Localization localization) { - return new SoundcloudSearchExtractor(this, queryHandler, localization); - } - @Override public SearchQueryHandlerFactory getSearchQHFactory() { return new SoundcloudSearchQueryHandlerFactory(); @@ -55,23 +43,28 @@ public class SoundcloudService extends StreamingService { @Override - public StreamExtractor getStreamExtractor(LinkHandler LinkHandler, Localization localization) { - return new SoundcloudStreamExtractor(this, LinkHandler, localization); + public StreamExtractor getStreamExtractor(LinkHandler LinkHandler) { + return new SoundcloudStreamExtractor(this, LinkHandler); } @Override - public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler, Localization localization) { - return new SoundcloudChannelExtractor(this, linkHandler, localization); + public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) { + return new SoundcloudChannelExtractor(this, linkHandler); } @Override - public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler, Localization localization) { - return new SoundcloudPlaylistExtractor(this, linkHandler, localization); + public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) { + return new SoundcloudPlaylistExtractor(this, linkHandler); } @Override - public SuggestionExtractor getSuggestionExtractor(Localization localization) { - return new SoundcloudSuggestionExtractor(getServiceId(), localization); + public SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler) { + return new SoundcloudSearchExtractor(this, queryHandler); + } + + @Override + public SoundcloudSuggestionExtractor getSuggestionExtractor() { + return new SoundcloudSuggestionExtractor(this); } @Override @@ -80,15 +73,14 @@ public class SoundcloudService extends StreamingService { @Override public KioskExtractor createNewKiosk(StreamingService streamingService, String url, - String id, - Localization local) + String id) throws ExtractionException { return new SoundcloudChartsExtractor(SoundcloudService.this, - new SoundcloudChartsLinkHandlerFactory().fromUrl(url), id, local); + new SoundcloudChartsLinkHandlerFactory().fromUrl(url), id); } }; - KioskList list = new KioskList(getServiceId()); + KioskList list = new KioskList(this); // add kiosks here e.g.: final SoundcloudChartsLinkHandlerFactory h = new SoundcloudChartsLinkHandlerFactory(); @@ -103,7 +95,6 @@ public class SoundcloudService extends StreamingService { return list; } - @Override public SubscriptionExtractor getSubscriptionExtractor() { return new SoundcloudSubscriptionExtractor(this); @@ -115,9 +106,9 @@ public class SoundcloudService extends StreamingService { } @Override - public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler, Localization localization) + public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler) throws ExtractionException { return null; } - + } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java index b842d85af..0fa636e7f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java @@ -4,26 +4,28 @@ import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; import org.schabi.newpipe.extractor.*; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.extractor.stream.*; -import org.schabi.newpipe.extractor.utils.Localization; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; import java.util.List; public class SoundcloudStreamExtractor extends StreamExtractor { private JsonObject track; - public SoundcloudStreamExtractor(StreamingService service, LinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public SoundcloudStreamExtractor(StreamingService service, LinkHandler linkHandler) { + super(service, linkHandler); } @Override @@ -50,8 +52,14 @@ public class SoundcloudStreamExtractor extends StreamExtractor { @Nonnull @Override - public String getUploadDate() throws ParsingException { - return SoundcloudParsingHelper.toTextualDate(track.getString("created_at")); + public String getTextualUploadDate() { + return track.getString("created_at"); + } + + @Nonnull + @Override + public Calendar getUploadDate() throws ParsingException { + return SoundcloudParsingHelper.parseDate(getTextualUploadDate()); } @Nonnull @@ -139,7 +147,7 @@ public class SoundcloudStreamExtractor extends StreamExtractor { String apiUrl = "https://api.soundcloud.com/i1/tracks/" + urlEncode(getId()) + "/streams" + "?client_id=" + urlEncode(SoundcloudParsingHelper.clientId()); - String response = dl.download(apiUrl); + String response = dl.get(apiUrl, getExtractorLocalization()).responseBody(); JsonObject responseObject; try { responseObject = JsonParser.object().from(response); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java index a81421f01..7453c5ada 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java @@ -43,15 +43,13 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto } @Override - public String getTextualUploadDate() throws ParsingException { - return SoundcloudParsingHelper.toTextualDate(getCreatedAt()); + public String getTextualUploadDate() { + return itemObject.getString("created_at"); } @Override public Calendar getUploadDate() throws ParsingException { - Calendar uploadTime = Calendar.getInstance(); - uploadTime.setTime(SoundcloudParsingHelper.parseDate(getCreatedAt())); - return uploadTime; + return SoundcloudParsingHelper.parseDate(getTextualUploadDate()); } private String getCreatedAt() { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractor.java index f982ae9a2..b12f04673 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractor.java @@ -4,12 +4,12 @@ import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.SuggestionExtractor; +import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; import java.io.IOException; import java.net.URLEncoder; @@ -20,8 +20,8 @@ public class SoundcloudSuggestionExtractor extends SuggestionExtractor { public static final String CHARSET_UTF_8 = "UTF-8"; - public SoundcloudSuggestionExtractor(int serviceId, Localization localization) { - super(serviceId, localization); + public SoundcloudSuggestionExtractor(StreamingService service) { + super(service); } @Override @@ -35,7 +35,7 @@ public class SoundcloudSuggestionExtractor extends SuggestionExtractor { + "&client_id=" + SoundcloudParsingHelper.clientId() + "&limit=10"; - String response = dl.download(url); + String response = dl.get(url, getExtractorLocalization()).responseBody(); try { JsonArray collection = JsonParser.object().from(response).getArray("collection"); for (Object suggestion : collection) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java index 3b621b8f0..279a85130 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java @@ -1,43 +1,26 @@ package org.schabi.newpipe.extractor.services.youtube; -import static java.util.Arrays.asList; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.LIVE; -import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO; - import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.SuggestionExtractor; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.kiosk.KioskList; -import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; +import org.schabi.newpipe.extractor.linkhandler.*; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeCommentsExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubePlaylistExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSubscriptionExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSuggestionExtractor; -import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingExtractor; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeCommentsLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory; -import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory; +import org.schabi.newpipe.extractor.services.youtube.extractors.*; +import org.schabi.newpipe.extractor.services.youtube.linkHandler.*; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; + +import java.util.List; + +import static java.util.Arrays.asList; +import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.*; /* * Created by Christian Schabesberger on 23.08.15. @@ -65,11 +48,6 @@ public class YoutubeService extends StreamingService { super(id, "YouTube", asList(AUDIO, VIDEO, LIVE, COMMENTS)); } - @Override - public SearchExtractor getSearchExtractor(SearchQueryHandler query, Localization localization) { - return new YoutubeSearchExtractor(this, query, localization); - } - @Override public LinkHandlerFactory getStreamLHFactory() { return YoutubeStreamLinkHandlerFactory.getInstance(); @@ -91,28 +69,33 @@ public class YoutubeService extends StreamingService { } @Override - public StreamExtractor getStreamExtractor(LinkHandler linkHandler, Localization localization) { - return new YoutubeStreamExtractor(this, linkHandler, localization); + public StreamExtractor getStreamExtractor(LinkHandler linkHandler) { + return new YoutubeStreamExtractor(this, linkHandler); } @Override - public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler, Localization localization) { - return new YoutubeChannelExtractor(this, linkHandler, localization); + public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) { + return new YoutubeChannelExtractor(this, linkHandler); } @Override - public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler, Localization localization) { - return new YoutubePlaylistExtractor(this, linkHandler, localization); + public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) { + return new YoutubePlaylistExtractor(this, linkHandler); } @Override - public SuggestionExtractor getSuggestionExtractor(Localization localization) { - return new YoutubeSuggestionExtractor(getServiceId(), localization); + public SearchExtractor getSearchExtractor(SearchQueryHandler query) { + return new YoutubeSearchExtractor(this, query); + } + + @Override + public SuggestionExtractor getSuggestionExtractor() { + return new YoutubeSuggestionExtractor(this); } @Override public KioskList getKioskList() throws ExtractionException { - KioskList list = new KioskList(getServiceId()); + KioskList list = new KioskList(this); // add kiosks here e.g.: try { @@ -120,11 +103,10 @@ public class YoutubeService extends StreamingService { @Override public KioskExtractor createNewKiosk(StreamingService streamingService, String url, - String id, - Localization local) + String id) throws ExtractionException { return new YoutubeTrendingExtractor(YoutubeService.this, - new YoutubeTrendingLinkHandlerFactory().fromUrl(url), id, local); + new YoutubeTrendingLinkHandlerFactory().fromUrl(url), id); } }, new YoutubeTrendingLinkHandlerFactory(), "Trending"); list.setDefaultKiosk("Trending"); @@ -146,9 +128,52 @@ public class YoutubeService extends StreamingService { } @Override - public CommentsExtractor getCommentsExtractor(ListLinkHandler urlIdHandler, Localization localization) + public CommentsExtractor getCommentsExtractor(ListLinkHandler urlIdHandler) throws ExtractionException { - return new YoutubeCommentsExtractor(this, urlIdHandler, localization); + return new YoutubeCommentsExtractor(this, urlIdHandler); } + /*////////////////////////////////////////////////////////////////////////// + // Localization + //////////////////////////////////////////////////////////////////////////*/ + + // https://www.youtube.com/picker_ajax?action_language_json=1 + private static final List SUPPORTED_LANGUAGES = Localization.listFrom( + "af", "am", "ar", "az", "be", "bg", "bn", "bs", "ca", "cs", "da", "de", + "el", "en", "en-GB", "es", "es-419", "es-US", "et", "eu", "fa", "fi", "fil", "fr", + "fr-CA", "gl", "gu", "hi", "hr", "hu", "hy", "id", "is", "it", "iw", "ja", + "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", "mn", + "mr", "ms", "my", "ne", "nl", "no", "pa", "pl", "pt", "pt-PT", "ro", "ru", + "si", "sk", "sl", "sq", "sr", "sr-Latn", "sv", "sw", "ta", "te", "th", "tr", + "uk", "ur", "uz", "vi", "zh-CN", "zh-HK", "zh-TW", "zu" + ); + + // https://www.youtube.com/picker_ajax?action_country_json=1 + private static final List SUPPORTED_COUNTRIES = ContentCountry.listFrom( + "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", + "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", + "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", + "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", + "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", + "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", + "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", + "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", + "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", + "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", + "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", + "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", + "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", + "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", + "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW" + ); + + @Override + public List getSupportedLocalizations() { + return SUPPORTED_LANGUAGES; + } + + @Override + public List getSupportedCountries() { + return SUPPORTED_COUNTRIES; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java index 14c5a9ed1..3ba53bc2f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java @@ -1,32 +1,27 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; - import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; -import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.stream.TimeAgoParser; -import org.schabi.newpipe.extractor.utils.DonationLinkHelper; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Parser; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; import java.io.IOException; -import java.util.ArrayList; /* * Created by Christian Schabesberger on 25.07.16. @@ -54,18 +49,16 @@ public class YoutubeChannelExtractor extends ChannelExtractor { private static final String CHANNEL_FEED_BASE = "https://www.youtube.com/feeds/videos.xml?channel_id="; private static final String CHANNEL_URL_PARAMETERS = "/videos?view=0&flow=list&sort=dd&live_view=10000&gl=US&hl=en"; - private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); - private Document doc; - public YoutubeChannelExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public YoutubeChannelExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { String channelUrl = super.getUrl() + CHANNEL_URL_PARAMETERS; - final DownloadResponse response = downloader.get(channelUrl); + final Response response = downloader.get(channelUrl, getExtractorLocalization()); doc = YoutubeParsingHelper.parseAndCheckPage(channelUrl, response); } @@ -191,7 +184,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor { StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); JsonObject ajaxJson; try { - ajaxJson = JsonParser.object().from(NewPipe.getDownloader().download(pageUrl)); + final String response = getDownloader().get(pageUrl, getExtractorLocalization()).responseBody(); + ajaxJson = JsonParser.object().from(response); } catch (JsonParserException pe) { throw new ParsingException("Could not parse json data for next streams", pe); } @@ -231,6 +225,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor { final String uploaderName = getName(); final String uploaderUrl = getUrl(); + final TimeAgoParser timeAgoParser = getTimeAgoParser(); + for (final Element li : element.children()) { if (li.select("div[class=\"feed-item-dismissable\"]").first() != null) { collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsExtractor.java index aba43b2e8..1c377cc5c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsExtractor.java @@ -1,36 +1,31 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import javax.annotation.Nonnull; - -import org.schabi.newpipe.extractor.DownloadRequest; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; +import com.grack.nanojson.JsonArray; +import com.grack.nanojson.JsonObject; +import com.grack.nanojson.JsonParser; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.comments.CommentsExtractor; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor; import org.schabi.newpipe.extractor.comments.CommentsInfoItemsCollector; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.utils.JsonUtils; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Parser; -import com.grack.nanojson.JsonArray; -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; +import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; +import java.util.regex.Pattern; + +import static java.util.Collections.singletonList; public class YoutubeCommentsExtractor extends CommentsExtractor { @@ -44,8 +39,8 @@ public class YoutubeCommentsExtractor extends CommentsExtractor { private String title; private InfoItemsPage initPage; - public YoutubeCommentsExtractor(StreamingService service, ListLinkHandler uiHandler, Localization localization) { - super(service, uiHandler, localization); + public YoutubeCommentsExtractor(StreamingService service, ListLinkHandler uiHandler) { + super(service, uiHandler); } @Override @@ -130,7 +125,7 @@ public class YoutubeCommentsExtractor extends CommentsExtractor { for(Object c: comments) { if(c instanceof JsonObject) { - CommentsInfoItemExtractor extractor = new YoutubeCommentsInfoItemExtractor((JsonObject) c, getUrl()); + CommentsInfoItemExtractor extractor = new YoutubeCommentsInfoItemExtractor((JsonObject) c, getUrl(), getTimeAgoParser()); collector.commit(extractor); } } @@ -147,12 +142,11 @@ public class YoutubeCommentsExtractor extends CommentsExtractor { } @Override - public void onFetchPage(Downloader downloader) throws IOException, ExtractionException { - Map> requestHeaders = new HashMap<>(); - requestHeaders.put("User-Agent", Arrays.asList(USER_AGENT)); - DownloadRequest request = new DownloadRequest(null, requestHeaders); - DownloadResponse response = downloader.get(getUrl(), request); - String responseBody = response.getResponseBody(); + public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { + final Map> requestHeaders = new HashMap<>(); + requestHeaders.put("User-Agent", singletonList(USER_AGENT)); + final Response response = downloader.get(getUrl(), requestHeaders, getExtractorLocalization()); + String responseBody = response.responseBody(); ytClientVersion = findValue(responseBody, "INNERTUBE_CONTEXT_CLIENT_VERSION\":\"", "\""); ytClientName = Parser.matchGroup1(YT_CLIENT_NAME_PATTERN, responseBody); String commentsTokenInside = findValue(responseBody, "commentSectionRenderer", "}"); @@ -160,6 +154,7 @@ public class YoutubeCommentsExtractor extends CommentsExtractor { initPage = getPage(getNextPageUrl(commentsToken)); } + @Nonnull @Override public String getName() throws ParsingException { return title; @@ -168,13 +163,11 @@ public class YoutubeCommentsExtractor extends CommentsExtractor { private String makeAjaxRequest(String siteUrl) throws IOException, ReCaptchaException { Map> requestHeaders = new HashMap<>(); - requestHeaders.put("Accept", Arrays.asList("*/*")); - requestHeaders.put("User-Agent", Arrays.asList(USER_AGENT)); - requestHeaders.put("X-YouTube-Client-Version", Arrays.asList(ytClientVersion)); - requestHeaders.put("X-YouTube-Client-Name", Arrays.asList(ytClientName)); - DownloadRequest request = new DownloadRequest(null, requestHeaders); - - return NewPipe.getDownloader().get(siteUrl, request).getResponseBody(); + requestHeaders.put("Accept", singletonList("*/*")); + requestHeaders.put("User-Agent", singletonList(USER_AGENT)); + requestHeaders.put("X-YouTube-Client-Version", singletonList(ytClientVersion)); + requestHeaders.put("X-YouTube-Client-Name", singletonList(ytClientName)); + return getDownloader().get(siteUrl, requestHeaders, getExtractorLocalization()).responseBody(); } private String getDataString(Map params) throws UnsupportedEncodingException { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java index a118b44ef..f3e6df2a4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java @@ -1,21 +1,25 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; -import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor; -import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.utils.JsonUtils; -import org.schabi.newpipe.extractor.utils.Utils; - import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonObject; +import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor; +import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; +import org.schabi.newpipe.extractor.utils.JsonUtils; +import org.schabi.newpipe.extractor.utils.Utils; + +import java.util.Calendar; public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtractor { private final JsonObject json; private final String url; + private final TimeAgoParser timeAgoParser; - public YoutubeCommentsInfoItemExtractor(JsonObject json, String url) { + public YoutubeCommentsInfoItemExtractor(JsonObject json, String url, TimeAgoParser timeAgoParser) { this.json = json; this.url = url; + this.timeAgoParser = timeAgoParser; } @Override @@ -43,7 +47,7 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract } @Override - public String getPublishedTime() throws ParsingException { + public String getTextualPublishedTime() throws ParsingException { try { return YoutubeCommentsExtractor.getYoutubeText(JsonUtils.getObject(json, "publishedTimeText")); } catch (Exception e) { @@ -52,7 +56,17 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract } @Override - public Integer getLikeCount() throws ParsingException { + public Calendar getPublishedTime() throws ParsingException { + String textualPublishedTime = getTextualPublishedTime(); + if (timeAgoParser != null && textualPublishedTime != null && !textualPublishedTime.isEmpty()) { + return timeAgoParser.parse(textualPublishedTime); + } else { + return null; + } + } + + @Override + public int getLikeCount() throws ParsingException { try { return JsonUtils.getNumber(json, "likeCount").intValue(); } catch (Exception e) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java index 0d5668e9f..c16caf60a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java @@ -6,20 +6,19 @@ import com.grack.nanojson.JsonParserException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.stream.StreamType; -import org.schabi.newpipe.extractor.stream.TimeAgoParser; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; @@ -29,18 +28,16 @@ import java.io.IOException; @SuppressWarnings("WeakerAccess") public class YoutubePlaylistExtractor extends PlaylistExtractor { - private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); - private Document doc; - public YoutubePlaylistExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public YoutubePlaylistExtractor(StreamingService service, ListLinkHandler linkHandler) { + super(service, linkHandler); } @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { final String url = getUrl(); - final DownloadResponse response = downloader.get(url); + final Response response = downloader.get(url, getExtractorLocalization()); doc = YoutubeParsingHelper.parseAndCheckPage(url, response); } @@ -144,7 +141,8 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); JsonObject pageJson; try { - pageJson = JsonParser.object().from(getDownloader().download(pageUrl)); + final String responseBody = getDownloader().get(pageUrl, getExtractorLocalization()).responseBody(); + pageJson = JsonParser.object().from(responseBody); } catch (JsonParserException pe) { throw new ParsingException("Could not parse ajax json", pe); } @@ -190,6 +188,8 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor { } final LinkHandlerFactory streamLinkHandlerFactory = getService().getStreamLHFactory(); + final TimeAgoParser timeAgoParser = getTimeAgoParser(); + for (final Element li : element.children()) { if(isDeletedItem(li)) { continue; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java index c3f234aaf..f6236e93a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java @@ -3,17 +3,16 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector; import org.schabi.newpipe.extractor.search.SearchExtractor; -import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.utils.Parser; @@ -47,22 +46,21 @@ public class YoutubeSearchExtractor extends SearchExtractor { private Document doc; - public YoutubeSearchExtractor(StreamingService service, - SearchQueryHandler linkHandler, - Localization localization) { - super(service, linkHandler, localization); + public YoutubeSearchExtractor(StreamingService service, SearchQueryHandler linkHandler) { + super(service, linkHandler); } @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { final String url = getUrl(); - final DownloadResponse response = downloader.get(url, getLocalization()); + final Response response = downloader.get(url, getExtractorLocalization()); doc = YoutubeParsingHelper.parseAndCheckPage(url, response); } + @Nonnull @Override public String getUrl() throws ParsingException { - return super.getUrl() + "&gl="+ getLocalization().getCountry(); + return super.getUrl() + "&gl=" + getExtractorContentCountry().getCountryCode(); } @Override @@ -88,8 +86,8 @@ public class YoutubeSearchExtractor extends SearchExtractor { @Override public InfoItemsPage getPage(String pageUrl) throws IOException, ExtractionException { - String site = getDownloader().download(pageUrl); - doc = Jsoup.parse(site, pageUrl); + final String response = getDownloader().get(pageUrl, getExtractorLocalization()).responseBody(); + doc = Jsoup.parse(response, pageUrl); return new InfoItemsPage<>(collectItems(doc), getNextPageUrlFromCurrentUrl(pageUrl)); } @@ -110,6 +108,7 @@ public class YoutubeSearchExtractor extends SearchExtractor { InfoItemsSearchCollector collector = getInfoItemSearchCollector(); Element list = doc.select("ol[class=\"item-section\"]").first(); + final TimeAgoParser timeAgoParser = getTimeAgoParser(); for (Element item : list.children()) { /* First we need to determine which kind of item we are working with. @@ -130,7 +129,7 @@ public class YoutubeSearchExtractor extends SearchExtractor { // video item type } else if ((el = item.select("div[class*=\"yt-lockup-video\"]").first()) != null) { - collector.commit(new YoutubeStreamInfoItemExtractor(el, getService().getTimeAgoParser())); + collector.commit(new YoutubeStreamInfoItemExtractor(el, timeAgoParser)); } else if ((el = item.select("div[class*=\"yt-lockup-channel\"]").first()) != null) { collector.commit(new YoutubeChannelInfoItemExtractor(el)); } else if ((el = item.select("div[class*=\"yt-lockup-playlist\"]").first()) != null && 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 4c33a258c..242395371 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 @@ -11,16 +11,22 @@ import org.jsoup.select.Elements; import org.mozilla.javascript.Context; import org.mozilla.javascript.Function; import org.mozilla.javascript.ScriptableObject; -import org.schabi.newpipe.extractor.*; +import org.schabi.newpipe.extractor.MediaFormat; +import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Request; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.services.youtube.ItagItem; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.*; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.Parser; import org.schabi.newpipe.extractor.utils.Utils; @@ -75,8 +81,6 @@ public class YoutubeStreamExtractor extends StreamExtractor { /*//////////////////////////////////////////////////////////////////////////*/ - private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); - private Document doc; @Nullable private JsonObject playerArgs; @@ -89,8 +93,8 @@ public class YoutubeStreamExtractor extends StreamExtractor { private boolean isAgeRestricted; - public YoutubeStreamExtractor(StreamingService service, LinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public YoutubeStreamExtractor(StreamingService service, LinkHandler linkHandler) { + super(service, linkHandler); } /*////////////////////////////////////////////////////////////////////////// @@ -116,10 +120,12 @@ public class YoutubeStreamExtractor extends StreamExtractor { return name; } - @Nonnull @Override - public String getUploadDate() throws ParsingException { - assertPageFetched(); + public String getTextualUploadDate() throws ParsingException { + if (getStreamType().equals(StreamType.LIVE_STREAM)) { + return null; + } + try { return doc.select("meta[itemprop=datePublished]").attr(CONTENT); } catch (Exception e) {//todo: add fallback method @@ -127,6 +133,17 @@ public class YoutubeStreamExtractor extends StreamExtractor { } } + @Override + public Calendar getUploadDate() throws ParsingException { + final String textualUploadDate = getTextualUploadDate(); + + if (textualUploadDate == null) { + return null; + } + + return YoutubeParsingHelper.parseDateFrom(textualUploadDate); + } + @Nonnull @Override public String getThumbnailUrl() throws ParsingException { @@ -534,13 +551,14 @@ public class YoutubeStreamExtractor extends StreamExtractor { assertPageFetched(); try { StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); + final TimeAgoParser timeAgoParser = getTimeAgoParser(); Elements watch = doc.select("div[class=\"watch-sidebar-section\"]"); if (watch.size() < 1) { return null;// prevent the snackbar notification "report error" on age-restricted videos } - collector.commit(extractVideoPreviewInfo(watch.first().select("li").first())); + collector.commit(extractVideoPreviewInfo(watch.first().select("li").first(), timeAgoParser)); return collector.getItems().get(0); } catch (Exception e) { throw new ParsingException("Could not get next video", e); @@ -552,12 +570,14 @@ public class YoutubeStreamExtractor extends StreamExtractor { assertPageFetched(); try { StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); + final TimeAgoParser timeAgoParser = getTimeAgoParser(); + Element ul = doc.select("ul[id=\"watch-related\"]").first(); if (ul != null) { for (Element li : ul.children()) { // first check if we have a playlist. If so leave them out if (li.select("a[class*=\"content-link\"]").first() != null) { - collector.commit(extractVideoPreviewInfo(li)); + collector.commit(extractVideoPreviewInfo(li, timeAgoParser)); } } } @@ -617,8 +637,8 @@ public class YoutubeStreamExtractor extends StreamExtractor { @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { final String verifiedUrl = getUrl() + VERIFIED_URL_PARAMS; - final DownloadResponse response = downloader.get(verifiedUrl); - pageHtml = response.getResponseBody(); + final Response response = downloader.get(verifiedUrl, getExtractorLocalization()); + pageHtml = response.responseBody(); doc = YoutubeParsingHelper.parseAndCheckPage(verifiedUrl, response); final String playerUrl; @@ -626,7 +646,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { if (!doc.select("meta[property=\"og:restrictions:age\"").isEmpty()) { final EmbeddedInfo info = getEmbeddedInfo(); final String videoInfoUrl = getVideoInfoUrl(getId(), info.sts); - final String infoPageResponse = downloader.download(videoInfoUrl); + final String infoPageResponse = downloader.get(videoInfoUrl, getExtractorLocalization()).responseBody(); videoInfoPage.putAll(Parser.compatParseMap(infoPageResponse)); playerUrl = info.url; isAgeRestricted = true; @@ -715,7 +735,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { try { final Downloader downloader = NewPipe.getDownloader(); final String embedUrl = "https://www.youtube.com/embed/" + getId(); - final String embedPageContent = downloader.download(embedUrl); + final String embedPageContent = downloader.get(embedUrl, getExtractorLocalization()).responseBody(); // Get player url final String assetsPattern = "\"assets\":.+?\"js\":\\s*(\"[^\"]+\")"; @@ -750,7 +770,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { playerUrl = "https://youtube.com" + playerUrl; } - final String playerCode = downloader.download(playerUrl); + final String playerCode = downloader.get(playerUrl, getExtractorLocalization()).responseBody(); final String decryptionFunctionName = getDecryptionFuncName(playerCode); final String functionPattern = "(" @@ -933,7 +953,7 @@ public class YoutubeStreamExtractor extends StreamExtractor { * Provides information about links to other videos on the video page, such as related videos. * This is encapsulated in a StreamInfoItem object, which is a subset of the fields in a full StreamInfo. */ - private StreamInfoItemExtractor extractVideoPreviewInfo(final Element li) { + private StreamInfoItemExtractor extractVideoPreviewInfo(final Element li, final TimeAgoParser timeAgoParser) { return new YoutubeStreamInfoItemExtractor(li, timeAgoParser) { @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 763c25380..162e2e49f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -6,7 +6,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; -import org.schabi.newpipe.extractor.stream.TimeAgoParser; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nullable; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSuggestionExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSuggestionExtractor.java index 77a85c72a..d41d90c55 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSuggestionExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSuggestionExtractor.java @@ -3,12 +3,12 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import com.grack.nanojson.JsonArray; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.extractor.Downloader; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.SuggestionExtractor; +import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; import java.io.IOException; import java.net.URLEncoder; @@ -39,8 +39,8 @@ public class YoutubeSuggestionExtractor extends SuggestionExtractor { public static final String CHARSET_UTF_8 = "UTF-8"; - public YoutubeSuggestionExtractor(int serviceId, Localization localization) { - super(serviceId, localization); + public YoutubeSuggestionExtractor(StreamingService service) { + super(service); } @Override @@ -52,10 +52,10 @@ public class YoutubeSuggestionExtractor extends SuggestionExtractor { + "?client=" + "youtube" //"firefox" for JSON, 'toolbar' for xml + "&jsonp=" + "JP" + "&ds=" + "yt" - + "&hl=" + URLEncoder.encode(getLocalization().getCountry(), CHARSET_UTF_8) + + "&gl=" + URLEncoder.encode(getExtractorContentCountry().getCountryCode(), CHARSET_UTF_8) + "&q=" + URLEncoder.encode(query, CHARSET_UTF_8); - String response = dl.download(url); + String response = dl.get(url, getExtractorLocalization()).responseBody(); // trim JSONP part "JP(...)" response = response.substring(3, response.length()-1); try { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java index 31e743542..a4014191e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeTrendingExtractor.java @@ -20,48 +20,40 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; * along with NewPipe. If not, see . */ -import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.Downloader; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; +import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; -import org.schabi.newpipe.extractor.utils.Localization; -import org.schabi.newpipe.extractor.stream.TimeAgoParser; import javax.annotation.Nonnull; import java.io.IOException; public class YoutubeTrendingExtractor extends KioskExtractor { - private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser(); - private Document doc; public YoutubeTrendingExtractor(StreamingService service, ListLinkHandler linkHandler, - String kioskId, - Localization localization) { - super(service, linkHandler, kioskId, localization); + String kioskId) { + super(service, linkHandler, kioskId); } @Override public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { - final String contentCountry = getLocalization().getCountry(); - String url = getUrl(); - if(contentCountry != null && !contentCountry.isEmpty()) { - url += "?gl=" + contentCountry; - } + final String url = getUrl() + + "?gl=" + getExtractorContentCountry().getCountryCode(); - final DownloadResponse response = downloader.get(url); + final Response response = downloader.get(url, getExtractorLocalization()); doc = YoutubeParsingHelper.parseAndCheckPage(url, response); } @@ -93,6 +85,9 @@ public class YoutubeTrendingExtractor extends KioskExtractor { public InfoItemsPage getInitialPage() throws ParsingException { StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); Elements uls = doc.select("ul[class*=\"expanded-shelf-content-list\"]"); + + final TimeAgoParser timeAgoParser = getTimeAgoParser(); + for(Element ul : uls) { for(final Element li : ul.children()) { final Element el = li.select("div[class*=\"yt-lockup-dismissable\"]").first(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeParsingHelper.java index 120275caa..0e76ddf67 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeParsingHelper.java @@ -3,11 +3,15 @@ package org.schabi.newpipe.extractor.services.youtube.linkHandler; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; -import org.schabi.newpipe.extractor.DownloadResponse; +import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import java.net.URL; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; /* * Created by Christian Schabesberger on 02.03.16. @@ -39,8 +43,8 @@ public class YoutubeParsingHelper { "input[name*=\"action_recaptcha_verify\"]" }; - public static Document parseAndCheckPage(final String url, final DownloadResponse response) throws ReCaptchaException { - final Document document = Jsoup.parse(response.getResponseBody(), url); + public static Document parseAndCheckPage(final String url, final Response response) throws ReCaptchaException { + final Document document = Jsoup.parse(response.responseBody(), url); for (String detectionSelector : RECAPTCHA_DETECTION_SELECTORS) { if (!document.select(detectionSelector).isEmpty()) { @@ -113,4 +117,17 @@ public class YoutubeParsingHelper { + Long.parseLong(minutes)) * 60) + Long.parseLong(seconds); } + + public static Calendar parseDateFrom(String textualUploadDate) throws ParsingException { + Date date; + try { + date = new SimpleDateFormat("yyyy-MM-dd").parse(textualUploadDate); + } catch (ParseException e) { + throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"", e); + } + + final Calendar uploadDate = Calendar.getInstance(); + uploadDate.setTime(date); + return uploadDate; + } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java index 46ffe8a8a..7957de2a5 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java @@ -26,13 +26,13 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Parser; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; import java.util.List; @@ -43,18 +43,36 @@ public abstract class StreamExtractor extends Extractor { public static final int NO_AGE_LIMIT = 0; - public StreamExtractor(StreamingService service, LinkHandler linkHandler, Localization localization) { - super(service, linkHandler, localization); + public StreamExtractor(StreamingService service, LinkHandler linkHandler) { + super(service, linkHandler); } /** - * The day on which the stream got uploaded/created. The return information should be in the format - * dd.mm.yyyy, however it NewPipe will not crash if its not. - * @return The day on which the stream got uploaded. - * @throws ParsingException + * The original textual date provided by the service. Should be used as a fallback if + * {@link #getUploadDate()} isn't provided by the service, or it fails for some reason. + * + *

If the stream is a live stream, {@code null} should be returned.

+ * + * @return The original textual date provided by the service, or {@code null}. + * @throws ParsingException if there is an error in the extraction + * @see #getUploadDate() */ - @Nonnull - public abstract String getUploadDate() throws ParsingException; + @Nullable + public abstract String getTextualUploadDate() throws ParsingException; + + /** + * A more general {@code Calendar} instance set to the date provided by the service.
+ * Implementations usually will just parse the date returned from the {@link #getTextualUploadDate()}. + * + *

If the stream is a live stream, {@code null} should be returned.

+ * + * @return The date this item was uploaded, or {@code null}. + * @throws ParsingException if there is an error in the extraction + * or the extracted date couldn't be parsed. + * @see #getTextualUploadDate() + */ + @Nullable + public abstract Calendar getUploadDate() throws ParsingException; /** * This will return the url to the thumbnail of the stream. Try to return the medium resolution here. diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java index b07e2270c..8a049faa0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.extractor.stream; import java.io.IOException; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; import org.schabi.newpipe.extractor.Info; @@ -228,6 +229,11 @@ public class StreamInfo extends Info { } catch (Exception e) { streamInfo.addError(e); } + try { + streamInfo.setTextualUploadDate(extractor.getTextualUploadDate()); + } catch (Exception e) { + streamInfo.addError(e); + } try { streamInfo.setUploadDate(extractor.getUploadDate()); } catch (Exception e) { @@ -271,7 +277,8 @@ public class StreamInfo extends Info { private StreamType streamType; private String thumbnailUrl = ""; - private String uploadDate = ""; + private String textualUploadDate; + private Calendar uploadDate; private long duration = -1; private int ageLimit = -1; private String description; @@ -327,11 +334,19 @@ public class StreamInfo extends Info { this.thumbnailUrl = thumbnailUrl; } - public String getUploadDate() { + public String getTextualUploadDate() { + return textualUploadDate; + } + + public void setTextualUploadDate(String textualUploadDate) { + this.textualUploadDate = textualUploadDate; + } + + public Calendar getUploadDate() { return uploadDate; } - public void setUploadDate(String uploadDate) { + public void setUploadDate(Calendar uploadDate) { this.uploadDate = uploadDate; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java index 3f786baec..202188a79 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java @@ -22,6 +22,7 @@ package org.schabi.newpipe.extractor.stream; import org.schabi.newpipe.extractor.InfoItem; +import javax.annotation.Nullable; import java.util.Calendar; /** @@ -83,18 +84,20 @@ public class StreamInfoItem extends InfoItem { * @return The original textual upload date as returned by the streaming service. * @see #getUploadDate() */ + @Nullable public String getTextualUploadDate() { return textualUploadDate; } - public void setTextualUploadDate(String upload_date) { - this.textualUploadDate = upload_date; + public void setTextualUploadDate(String uploadDate) { + this.textualUploadDate = uploadDate; } /** * @return The (approximated) date and time this item was uploaded or {@code null}. * @see #getTextualUploadDate() */ + @Nullable public Calendar getUploadDate() { return uploadDate; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java index 4184131e3..154e74651 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java @@ -66,11 +66,10 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor { String getUploaderUrl() throws ParsingException; /** - * Extract the textual upload date of this item. - * The original textual date provided by the service may be used if it is short; - * otherwise the format "yyyy-MM-dd" or an locale specific version is preferred. + * The original textual date provided by the service. Should be used as a fallback if + * {@link #getUploadDate()} isn't provided by the service, or it fails for some reason. * - * @return The original textual upload date. + * @return The original textual date provided by the service. * @throws ParsingException if there is an error in the extraction * @see #getUploadDate() */ diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/suggestion/SuggestionExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/suggestion/SuggestionExtractor.java new file mode 100644 index 000000000..6b0dd28ae --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/suggestion/SuggestionExtractor.java @@ -0,0 +1,51 @@ +package org.schabi.newpipe.extractor.suggestion; + +import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.extractor.localization.Localization; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.List; + +public abstract class SuggestionExtractor { + private final StreamingService service; + @Nullable private Localization forcedLocalization; + @Nullable private ContentCountry forcedContentCountry; + + public SuggestionExtractor(StreamingService service) { + this.service = service; + } + + public abstract List suggestionList(String query) throws IOException, ExtractionException; + + public int getServiceId() { + return service.getServiceId(); + } + + public StreamingService getService() { + return service; + } + + // TODO: Create a more general Extractor class + + public void forceLocalization(@Nullable Localization localization) { + this.forcedLocalization = localization; + } + + public void forceContentCountry(@Nullable ContentCountry contentCountry) { + this.forcedContentCountry = contentCountry; + } + + @Nonnull + public Localization getExtractorLocalization() { + return forcedLocalization == null ? getService().getLocalization() : forcedLocalization; + } + + @Nonnull + public ContentCountry getExtractorContentCountry() { + return forcedContentCountry == null ? getService().getContentCountry() : forcedContentCountry; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/DashMpdParser.java b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/DashMpdParser.java index 9c1a8a16a..7b954a4c3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/DashMpdParser.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/DashMpdParser.java @@ -1,6 +1,6 @@ package org.schabi.newpipe.extractor.utils; -import org.schabi.newpipe.extractor.Downloader; +import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; @@ -120,7 +120,7 @@ public class DashMpdParser { String dashDoc; Downloader downloader = NewPipe.getDownloader(); try { - dashDoc = downloader.download(streamInfo.getDashMpdUrl()); + dashDoc = downloader.get(streamInfo.getDashMpdUrl()).responseBody(); } catch (IOException ioe) { throw new DashMpdParsingException("Could not get dash mpd: " + streamInfo.getDashMpdUrl(), ioe); } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/Localization.java b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/Localization.java deleted file mode 100644 index d4f5ddbc0..000000000 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/utils/Localization.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.schabi.newpipe.extractor.utils; - -public class Localization { - private final String country; - private final String language; - - public Localization(String country, String language) { - this.country = country; - this.language = language; - } - - public String getCountry() { - return country; - } - - public String getLanguage() { - return language; - } -} diff --git a/extractor/src/test/java/org/schabi/newpipe/Downloader.java b/extractor/src/test/java/org/schabi/newpipe/Downloader.java deleted file mode 100644 index 172b2ca78..000000000 --- a/extractor/src/test/java/org/schabi/newpipe/Downloader.java +++ /dev/null @@ -1,258 +0,0 @@ -package org.schabi.newpipe; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; - -import org.schabi.newpipe.extractor.DownloadRequest; -import org.schabi.newpipe.extractor.DownloadResponse; -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; -import org.schabi.newpipe.extractor.utils.Localization; - -import static java.util.Collections.singletonList; - -/* - * Created by Christian Schabesberger on 28.01.16. - * - * Copyright (C) Christian Schabesberger 2016 - * Downloader.java is part of NewPipe. - * - * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ - -public class Downloader implements org.schabi.newpipe.extractor.Downloader { - - private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"; - private static final String DEFAULT_HTTP_ACCEPT_LANGUAGE = "en"; - private static String mCookies = ""; - - private static Downloader instance = null; - - private Downloader() { - } - - public static Downloader getInstance() { - if (instance == null) { - synchronized (Downloader.class) { - if (instance == null) { - instance = new Downloader(); - } - } - } - return instance; - } - - public static synchronized void setCookies(String cookies) { - Downloader.mCookies = cookies; - } - - public static synchronized String getCookies() { - return Downloader.mCookies; - } - - /** - * Download the text file at the supplied URL as in download(String), but set - * the HTTP header field "Accept-Language" to the supplied string. - * - * @param siteUrl the URL of the text file to return the contents of - - * @param localization the language and country (usually a 2-character code for both values) - * @return the contents of the specified text file - */ - public String download(String siteUrl, Localization localization) throws IOException, ReCaptchaException { - Map requestProperties = new HashMap<>(); - requestProperties.put("Accept-Language", localization.getLanguage()); - return download(siteUrl, requestProperties); - } - - /** - * Download the text file at the supplied URL as in download(String), but set - * the HTTP header field "Accept-Language" to the supplied string. - * - * @param siteUrl the URL of the text file to return the contents of - * @param customProperties set request header properties - * @return the contents of the specified text file - * @throws IOException - */ - public String download(String siteUrl, Map customProperties) - throws IOException, ReCaptchaException { - URL url = new URL(siteUrl); - HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); - for (Map.Entry pair : customProperties.entrySet()) { - con.setRequestProperty(pair.getKey(), pair.getValue()); - } - return dl(con); - } - - /** - * Common functionality between download(String url) and download(String url, - * String language) - */ - private static String dl(HttpsURLConnection con) throws IOException, ReCaptchaException { - StringBuilder response = new StringBuilder(); - BufferedReader in = null; - - try { - - con.setRequestMethod("GET"); - setDefaults(con); - - in = new BufferedReader(new InputStreamReader(con.getInputStream())); - String inputLine; - - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - } catch (UnknownHostException uhe) {// thrown when there's no internet - // connection - throw new IOException("unknown host or no network", uhe); - // Toast.makeText(getActivity(), uhe.getMessage(), - // Toast.LENGTH_LONG).show(); - } catch (Exception e) { - /* - * HTTP 429 == Too Many Request Receive from Youtube.com = ReCaptcha challenge - * request See : https://github.com/rg3/youtube-dl/issues/5138 - */ - if (con.getResponseCode() == 429) { - throw new ReCaptchaException("reCaptcha Challenge requested", con.getURL().toString()); - } - - throw new IOException(con.getResponseCode() + " " + con.getResponseMessage(), e); - } finally { - if (in != null) { - in.close(); - } - } - - return response.toString(); - } - - private static void setDefaults(HttpsURLConnection con) { - - con.setConnectTimeout(30 * 1000);// 30s - con.setReadTimeout(30 * 1000);// 30s - - // set default user agent - if (null == con.getRequestProperty("User-Agent")) { - con.setRequestProperty("User-Agent", USER_AGENT); - } - - // add default cookies - if (getCookies().length() > 0) { - con.addRequestProperty("Cookie", getCookies()); - } - } - - /** - * Download (via HTTP) the text file located at the supplied URL, and return its - * contents. Primarily intended for downloading web pages. - * - * @param siteUrl the URL of the text file to download - * @return the contents of the specified text file - */ - public String download(String siteUrl) throws IOException, ReCaptchaException { - URL url = new URL(siteUrl); - HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); - // HttpsURLConnection con = NetCipher.getHttpsURLConnection(url); - con.setRequestProperty("Accept-Language", DEFAULT_HTTP_ACCEPT_LANGUAGE); - return dl(con); - } - - @Override - public DownloadResponse head(String siteUrl) throws IOException, ReCaptchaException { - final HttpsURLConnection con = (HttpsURLConnection) new URL(siteUrl).openConnection(); - - try { - con.setRequestMethod("HEAD"); - setDefaults(con); - } catch (Exception e) { - /* - * HTTP 429 == Too Many Request Receive from Youtube.com = ReCaptcha challenge - * request See : https://github.com/rg3/youtube-dl/issues/5138 - */ - if (con.getResponseCode() == 429) { - throw new ReCaptchaException("reCaptcha Challenge requested", con.getURL().toString()); - } - - throw new IOException(con.getResponseCode() + " " + con.getResponseMessage(), e); - } - - return new DownloadResponse(con.getResponseCode(), null, con.getHeaderFields()); - } - - @Override - public DownloadResponse get(String siteUrl, Localization localization) throws IOException, ReCaptchaException { - final Map> requestHeaders = new HashMap<>(); - requestHeaders.put("Accept-Language", singletonList(localization.getLanguage())); - - return get(siteUrl, new DownloadRequest(null, requestHeaders)); - } - - @Override - public DownloadResponse get(String siteUrl, DownloadRequest request) - throws IOException, ReCaptchaException { - URL url = new URL(siteUrl); - HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); - for (Map.Entry> pair : request.getRequestHeaders().entrySet()) { - for(String value: pair.getValue()) { - con.addRequestProperty(pair.getKey(), value); - } - } - String responseBody = dl(con); - return new DownloadResponse(con.getResponseCode(), responseBody, con.getHeaderFields()); - } - - @Override - public DownloadResponse get(String siteUrl) throws IOException, ReCaptchaException { - return get(siteUrl, DownloadRequest.emptyRequest); - } - - @Override - public DownloadResponse post(String siteUrl, DownloadRequest request) - throws IOException, ReCaptchaException { - URL url = new URL(siteUrl); - HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); - con.setRequestMethod("POST"); - for (Map.Entry> pair : request.getRequestHeaders().entrySet()) { - for(String value: pair.getValue()) { - con.addRequestProperty(pair.getKey(), value); - } - } - // set fields to default if not set already - setDefaults(con); - - if(null != request.getRequestBody()) { - byte[] postDataBytes = request.getRequestBody().getBytes("UTF-8"); - con.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); - con.setDoOutput(true); - con.getOutputStream().write(postDataBytes); - } - - StringBuilder sb = new StringBuilder(); - try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { - String inputLine; - while ((inputLine = in.readLine()) != null) { - sb.append(inputLine); - } - } - return new DownloadResponse(con.getResponseCode(), sb.toString(), con.getHeaderFields()); - } -} diff --git a/extractor/src/test/java/org/schabi/newpipe/DownloaderTestImpl.java b/extractor/src/test/java/org/schabi/newpipe/DownloaderTestImpl.java new file mode 100644 index 000000000..948975a05 --- /dev/null +++ b/extractor/src/test/java/org/schabi/newpipe/DownloaderTestImpl.java @@ -0,0 +1,120 @@ +package org.schabi.newpipe; + +import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.downloader.Request; +import org.schabi.newpipe.extractor.downloader.Response; +import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; +import org.schabi.newpipe.extractor.localization.Localization; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.net.ssl.HttpsURLConnection; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import java.util.Map; + +public class DownloaderTestImpl extends Downloader { + + private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"; + private static final String DEFAULT_HTTP_ACCEPT_LANGUAGE = "en"; + + private static DownloaderTestImpl instance = null; + + private DownloaderTestImpl() { + } + + public static DownloaderTestImpl getInstance() { + if (instance == null) { + synchronized (DownloaderTestImpl.class) { + if (instance == null) { + instance = new DownloaderTestImpl(); + } + } + } + return instance; + } + + private void setDefaultHeaders(URLConnection connection) { + connection.setRequestProperty("User-Agent", USER_AGENT); + connection.setRequestProperty("Accept-Language", DEFAULT_HTTP_ACCEPT_LANGUAGE); + } + + @Override + public Response execute(@Nonnull Request request) throws IOException, ReCaptchaException { + final String httpMethod = request.httpMethod(); + final String url = request.url(); + final Map> headers = request.headers(); + @Nullable final byte[] dataToSend = request.dataToSend(); + @Nullable final Localization localization = request.localization(); + + final HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + + connection.setConnectTimeout(30 * 1000); // 30s + connection.setReadTimeout(30 * 1000); // 30s + connection.setRequestMethod(httpMethod); + + setDefaultHeaders(connection); + + for (Map.Entry> pair : headers.entrySet()) { + final String headerName = pair.getKey(); + final List headerValueList = pair.getValue(); + + if (headerValueList.size() > 1) { + connection.setRequestProperty(headerName, null); + for (String headerValue : headerValueList) { + connection.addRequestProperty(headerName, headerValue); + } + } else if (headerValueList.size() == 1) { + connection.setRequestProperty(headerName, headerValueList.get(0)); + } + } + + @Nullable OutputStream outputStream = null; + @Nullable InputStreamReader input = null; + try { + if (dataToSend != null && dataToSend.length > 0) { + connection.setDoOutput(true); + connection.setRequestProperty("Content-Length", dataToSend.length + ""); + outputStream = connection.getOutputStream(); + outputStream.write(dataToSend); + } + + final InputStream inputStream = connection.getInputStream(); + final StringBuilder response = new StringBuilder(); + + // Not passing any charset for decoding here... something to keep in mind. + input = new InputStreamReader(inputStream); + + int readCount; + char[] buffer = new char[32 * 1024]; + while ((readCount = input.read(buffer)) != -1) { + response.append(buffer, 0, readCount); + } + + final int responseCode = connection.getResponseCode(); + final String responseMessage = connection.getResponseMessage(); + final Map> responseHeaders = connection.getHeaderFields(); + + return new Response(responseCode, responseMessage, responseHeaders, response.toString()); + } catch (Exception e) { + /* + * HTTP 429 == Too Many Request + * Receive from Youtube.com = ReCaptcha challenge request + * See : https://github.com/rg3/youtube-dl/issues/5138 + */ + if (connection.getResponseCode() == 429) { + throw new ReCaptchaException("reCaptcha Challenge requested", url); + } + + throw new IOException(connection.getResponseCode() + " " + connection.getResponseMessage(), e); + } finally { + if (outputStream != null) outputStream.close(); + if (input != null) input.close(); + } + } +} diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceExtractorTest.java index 3ea6aaaae..b9c67c4e6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceExtractorTest.java @@ -2,11 +2,10 @@ package org.schabi.newpipe.extractor.services.media_ccc; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceExtractor; -import org.schabi.newpipe.extractor.utils.Localization; import static junit.framework.TestCase.assertEquals; import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; @@ -19,7 +18,7 @@ public class MediaCCCConferenceExtractorTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("en", "en_GB")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getChannelExtractor("https://api.media.ccc.de/public/conferences/froscon2017"); extractor.fetchPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceListExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceListExtractorTest.java index 2116916f2..252e4dbb4 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceListExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCConferenceListExtractorTest.java @@ -1,18 +1,17 @@ package org.schabi.newpipe.extractor.services.media_ccc; + import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceKiosk; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.List; -import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; import static org.junit.Assert.assertTrue; +import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; /** @@ -24,7 +23,7 @@ public class MediaCCCConferenceListExtractorTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("en", "en_GB")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getKioskList().getDefaultKioskExtractor(); extractor.fetchPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCOggTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCOggTest.java index 54d81f160..781f91389 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCOggTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCOggTest.java @@ -2,13 +2,11 @@ package org.schabi.newpipe.extractor.services.media_ccc; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor; import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.StreamExtractor; -import org.schabi.newpipe.extractor.utils.Localization; - import static junit.framework.TestCase.assertEquals; import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; @@ -22,7 +20,7 @@ public class MediaCCCOggTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getStreamExtractor("https://api.media.ccc.de/public/events/1317"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorAllTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorAllTest.java index 8dfdb0a92..dc38338e6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorAllTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorAllTest.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.media_ccc; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; @@ -11,7 +11,6 @@ import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.Arrays; @@ -28,10 +27,9 @@ public class MediaCCCSearchExtractorAllTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getSearchExtractor( new MediaCCCSearchQueryHandlerFactory() - .fromQuery("c3", Arrays.asList(new String[0]), "") - ,new Localization("GB", "en")); + .fromQuery("c3", Arrays.asList(new String[0]), "")); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorConferencesTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorConferencesTest.java index 4b7a8b266..18fbc2343 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorConferencesTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorConferencesTest.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.media_ccc; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; @@ -10,7 +10,6 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.Arrays; @@ -27,10 +26,9 @@ public class MediaCCCSearchExtractorConferencesTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getSearchExtractor( new MediaCCCSearchQueryHandlerFactory() - .fromQuery("c3", Arrays.asList(new String[] {"conferences"}), "") - ,new Localization("GB", "en")); + .fromQuery("c3", Arrays.asList(new String[]{"conferences"}), "")); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorEventsTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorEventsTest.java index 11b1fbdfb..1ed65a8d6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorEventsTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCSearchExtractorEventsTest.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.media_ccc; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; @@ -10,7 +10,6 @@ import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearchExtractor; import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.Arrays; @@ -28,10 +27,9 @@ public class MediaCCCSearchExtractorEventsTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getSearchExtractor( new MediaCCCSearchQueryHandlerFactory() - .fromQuery("linux", Arrays.asList(new String[] {"events"}), "") - ,new Localization("GB", "en")); + .fromQuery("linux", Arrays.asList(new String[]{"events"}), "")); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java index 8aba91535..9aa1ef025 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java @@ -1,13 +1,18 @@ package org.schabi.newpipe.extractor.services.media_ccc; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.BaseExtractorTest; -import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.stream.StreamExtractor; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; import static junit.framework.TestCase.assertEquals; import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; @@ -20,7 +25,7 @@ public class MediaCCCStreamExtractorTest implements BaseExtractorTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = MediaCCC.getStreamExtractor("https://api.media.ccc.de/public/events/8afc16c2-d76a-53f6-85e4-90494665835d"); extractor.fetchPage(); @@ -80,4 +85,16 @@ public class MediaCCCStreamExtractorTest implements BaseExtractorTest { public void testAudioStreams() throws Exception { assertEquals(2, extractor.getAudioStreams().size()); } + + @Test + public void testGetTextualUploadDate() throws ParsingException { + Assert.assertEquals("2018-05-11", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2018-05-11")); + Assert.assertEquals(instance, extractor.getUploadDate()); + } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractorTest.java index a5884de91..0de8e847c 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChannelExtractorTest.java @@ -2,12 +2,11 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty; @@ -24,7 +23,7 @@ public class SoundcloudChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudChannelExtractor) SoundCloud .getChannelExtractor("http://soundcloud.com/liluzivert/sets"); extractor.fetchPage(); @@ -108,7 +107,7 @@ public class SoundcloudChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudChannelExtractor) SoundCloud .getChannelExtractor("https://soundcloud.com/dubmatix"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractorTest.java index dea7a8a9c..d96b4c6e3 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsExtractorTest.java @@ -3,12 +3,11 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.List; @@ -24,7 +23,7 @@ public class SoundcloudChartsExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = SoundCloud .getKioskList() .getExtractorById("Top 50", null); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsLinkHandlerFactoryTest.java index 99c473bcc..6bcc2e73f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudChartsLinkHandlerFactoryTest.java @@ -2,10 +2,9 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.utils.Localization; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; @@ -20,7 +19,7 @@ public class SoundcloudChartsLinkHandlerFactoryTest { @BeforeClass public static void setUp() { linkHandler = new SoundcloudChartsLinkHandlerFactory(); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelperTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelperTest.java index 435ae446c..1c4f41596 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelperTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelperTest.java @@ -1,22 +1,21 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.*; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.*; public class SoundcloudParsingHelperTest { @BeforeClass public static void setUp() { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test public void assertThatHardcodedClientIdIsValid() throws Exception { assertTrue("Hardcoded client id is not valid anymore", - SoundcloudParsingHelper.checkIfHardcodedClientIdIsValid(Downloader.getInstance())); + SoundcloudParsingHelper.checkIfHardcodedClientIdIsValid(DownloaderTestImpl.getInstance())); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractorTest.java index ec020109e..c27dfdf8f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudPlaylistExtractorTest.java @@ -4,14 +4,13 @@ import org.hamcrest.CoreMatchers; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.services.BasePlaylistExtractorTest; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; @@ -27,7 +26,7 @@ public class SoundcloudPlaylistExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudPlaylistExtractor) SoundCloud .getPlaylistExtractor("https://soundcloud.com/liluzivert/sets/the-perfect-luv-tape-r?test=123"); extractor.fetchPage(); @@ -125,7 +124,7 @@ public class SoundcloudPlaylistExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudPlaylistExtractor) SoundCloud .getPlaylistExtractor("https://soundcloud.com/micky96/sets/house"); extractor.fetchPage(); @@ -217,7 +216,7 @@ public class SoundcloudPlaylistExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudPlaylistExtractor) SoundCloud .getPlaylistExtractor("https://soundcloud.com/user350509423/sets/edm-xxx"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java index c8a2a841c..9610a43af 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java @@ -1,17 +1,20 @@ package org.schabi.newpipe.extractor.services.soundcloud; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.stream.StreamType; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; @@ -25,7 +28,7 @@ public class SoundcloudStreamExtractorDefaultTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudStreamExtractor) SoundCloud.getStreamExtractor("https://soundcloud.com/liluzivert/do-what-i-want-produced-by-maaly-raw-don-cannon"); extractor.fetchPage(); } @@ -69,8 +72,15 @@ public class SoundcloudStreamExtractorDefaultTest { } @Test - public void testGetUploadDate() throws ParsingException { - assertEquals("2016-07-31", extractor.getUploadDate()); + public void testGetTextualUploadDate() throws ParsingException { + Assert.assertEquals("2016/07/31 18:18:07 +0000", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse("2016/07/31 18:18:07 +0000")); + Assert.assertEquals(instance, extractor.getUploadDate()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamLinkHandlerFactoryTest.java index 65b09e9b0..5d303d10d 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamLinkHandlerFactoryTest.java @@ -2,10 +2,9 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.ArrayList; import java.util.List; @@ -21,7 +20,7 @@ public class SoundcloudStreamLinkHandlerFactoryTest { @BeforeClass public static void setUp() throws Exception { linkHandler = SoundcloudStreamLinkHandlerFactory.getInstance(); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test(expected = IllegalArgumentException.class) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSubscriptionExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSubscriptionExtractorTest.java index ec5f84edb..507f1ec2e 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSubscriptionExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSubscriptionExtractorTest.java @@ -2,14 +2,13 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.ServiceList; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; import java.util.Arrays; @@ -26,7 +25,7 @@ public class SoundcloudSubscriptionExtractorTest { @BeforeClass public static void setupClass() { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); subscriptionExtractor = new SoundcloudSubscriptionExtractor(ServiceList.SoundCloud); urlHandler = ServiceList.SoundCloud.getChannelLHFactory(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractorTest.java index e1505917d..5d53a178b 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudSuggestionExtractorTest.java @@ -2,11 +2,10 @@ package org.schabi.newpipe.extractor.services.soundcloud; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.SuggestionExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; import java.io.IOException; @@ -21,7 +20,7 @@ public class SoundcloudSuggestionExtractorTest { @BeforeClass public static void setUp() { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); suggestionExtractor = SoundCloud.getSuggestionExtractor(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorChannelOnlyTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorChannelOnlyTest.java index 386fa9160..abd26951f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorChannelOnlyTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorChannelOnlyTest.java @@ -2,14 +2,14 @@ package org.schabi.newpipe.extractor.services.soundcloud.search; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; +import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchExtractor; import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static java.util.Arrays.asList; import static org.junit.Assert.*; @@ -19,9 +19,9 @@ public class SoundcloudSearchExtractorChannelOnlyTest extends SoundcloudSearchEx @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("DE", "de")); + NewPipe.init(DownloaderTestImpl.getInstance(), new Localization("de", "DE")); extractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert", - asList(SoundcloudSearchQueryHandlerFactory.USERS), null, new Localization("DE", "de")); + asList(SoundcloudSearchQueryHandlerFactory.USERS), null); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } @@ -29,7 +29,7 @@ public class SoundcloudSearchExtractorChannelOnlyTest extends SoundcloudSearchEx @Test public void testGetSecondPage() throws Exception { SoundcloudSearchExtractor secondExtractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert", - asList(SoundcloudSearchQueryHandlerFactory.USERS), null, new Localization("DE", "de")); + asList(SoundcloudSearchQueryHandlerFactory.USERS), null); ListExtractor.InfoItemsPage secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl()); assertTrue(Integer.toString(secondPage.getItems().size()), secondPage.getItems().size() >= 3); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorDefaultTest.java index 682641de8..685c52d7a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchExtractorDefaultTest.java @@ -2,22 +2,19 @@ package org.schabi.newpipe.extractor.services.soundcloud.search; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchExtractor; import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.Arrays; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; -import static org.schabi.newpipe.extractor.ServiceList.YouTube; /* * Created by Christian Schabesberger on 27.05.18 @@ -46,11 +43,10 @@ public class SoundcloudSearchExtractorDefaultTest extends SoundcloudSearchExtrac @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor( new SoundcloudSearchQueryHandlerFactory().fromQuery("lill uzi vert", - Arrays.asList(new String[]{"tracks"}), ""), - new Localization("GB", "en")); + Arrays.asList(new String[]{"tracks"}), "")); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchQHTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchQHTest.java index b0f02b5b7..58a7000d8 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchQHTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/search/SoundcloudSearchQHTest.java @@ -2,22 +2,19 @@ package org.schabi.newpipe.extractor.services.soundcloud.search; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.utils.Localization; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; -import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.PLAYLISTS; -import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.TRACKS; -import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.USERS; +import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.*; public class SoundcloudSearchQHTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } private static String removeClientId(String url) { diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java index c25fdd9cc..36c96c264 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java @@ -2,14 +2,14 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; @@ -25,7 +25,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("http://www.youtube.com/user/Gronkh"); extractor.fetchPage(); @@ -115,7 +115,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/user/Vsauce"); extractor.fetchPage(); @@ -206,7 +206,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q"); extractor.fetchPage(); @@ -308,7 +308,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/user/CaptainDisillusion/videos"); extractor.fetchPage(); @@ -398,7 +398,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/user/EminemVEVO/"); extractor.fetchPage(); @@ -491,7 +491,7 @@ public class YoutubeChannelExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java index 378308773..7b4814cf6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java @@ -2,11 +2,10 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -21,7 +20,7 @@ public class YoutubeChannelLinkHandlerFactoryTest { @BeforeClass public static void setUp() { linkHandler = YoutubeChannelLinkHandlerFactory.getInstance(); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java new file mode 100644 index 000000000..731225af2 --- /dev/null +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java @@ -0,0 +1,139 @@ +package org.schabi.newpipe.extractor.services.youtube; + +import org.junit.Ignore; +import org.junit.Test; +import org.schabi.newpipe.DownloaderTestImpl; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; + +import java.text.SimpleDateFormat; +import java.util.*; + +import static org.junit.Assert.fail; +import static org.schabi.newpipe.extractor.ServiceList.YouTube; +import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRelatedItems; + +/** + * A class that tests multiple channels and ranges of "time ago". + */ +@Ignore("Should be ran manually from time to time, as it's too time consuming.") +public class YoutubeChannelLocalizationTest { + private static final boolean DEBUG = true; + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + @Test + public void testAllSupportedLocalizations() throws Exception { + NewPipe.init(DownloaderTestImpl.getInstance()); + + testLocalizationsFor("https://www.youtube.com/user/NBCNews"); + testLocalizationsFor("https://www.youtube.com/channel/UCcmpeVbSSQlZRvHfdC-CRwg/videos"); + testLocalizationsFor("https://www.youtube.com/channel/UC65afEgL62PGFWXY7n6CUbA"); + testLocalizationsFor("https://www.youtube.com/channel/UCEOXxzW2vU0P-0THehuIIeg"); + } + + private void testLocalizationsFor(String channelUrl) throws Exception { + + final List supportedLocalizations = YouTube.getSupportedLocalizations(); +// final List supportedLocalizations = Arrays.asList(Localization.DEFAULT, new Localization("sr")); + final Map> results = new LinkedHashMap<>(); + + for (Localization currentLocalization : supportedLocalizations) { + if (DEBUG) System.out.println("Testing localization = " + currentLocalization); + + ListExtractor.InfoItemsPage itemsPage; + try { + final ChannelExtractor extractor = YouTube.getChannelExtractor(channelUrl); + extractor.forceLocalization(currentLocalization); + extractor.fetchPage(); + itemsPage = defaultTestRelatedItems(extractor, YouTube.getServiceId()); + } catch (Throwable e) { + System.out.println("[!] " + currentLocalization + " → failed"); + throw e; + } + + final List items = itemsPage.getItems(); + for (int i = 0; i < items.size(); i++) { + final StreamInfoItem item = items.get(i); + + String debugMessage = "[" + String.format("%02d", i) + "] " + + currentLocalization.getLocalizationCode() + " → " + item.getName() + + "\n:::: " + item.getStreamType() + ", views = " + item.getViewCount(); + final Calendar uploadDate = item.getUploadDate(); + if (uploadDate != null) { + String dateAsText = dateFormat.format(uploadDate.getTime()); + debugMessage += "\n:::: " + item.getTextualUploadDate() + + "\n:::: " + dateAsText; + } + if (DEBUG) System.out.println(debugMessage + "\n"); + } + results.put(currentLocalization, itemsPage.getItems()); + + if (DEBUG) System.out.println("\n===============================\n"); + } + + + // Check results + final List referenceList = results.get(Localization.DEFAULT); + boolean someFail = false; + + for (Map.Entry> currentResultEntry : results.entrySet()) { + if (currentResultEntry.getKey().equals(Localization.DEFAULT)) { + continue; + } + + final String currentLocalizationCode = currentResultEntry.getKey().getLocalizationCode(); + final String referenceLocalizationCode = Localization.DEFAULT.getLocalizationCode(); + if (DEBUG) { + System.out.println("Comparing " + referenceLocalizationCode + " with " + + currentLocalizationCode); + } + + final List currentList = currentResultEntry.getValue(); + if (referenceList.size() != currentList.size()) { + if (DEBUG) System.out.println("[!] " + currentLocalizationCode + " → Lists are not equal"); + someFail = true; + continue; + } + + for (int i = 0; i < referenceList.size() - 1; i++) { + final StreamInfoItem referenceItem = referenceList.get(i); + final StreamInfoItem currentItem = currentList.get(i); + + final Calendar referenceUploadDate = referenceItem.getUploadDate(); + final Calendar currentUploadDate = currentItem.getUploadDate(); + + final String referenceDateString = referenceUploadDate == null ? "null" : + dateFormat.format(referenceUploadDate.getTime()); + final String currentDateString = currentUploadDate == null ? "null" : + dateFormat.format(currentUploadDate.getTime()); + + long difference = -1; + if (referenceUploadDate != null && currentUploadDate != null) { + difference = Math.abs(referenceUploadDate.getTimeInMillis() - currentUploadDate.getTimeInMillis()); + } + + final boolean areTimeEquals = difference < 5 * 60 * 1000L; + + if (!areTimeEquals) { + System.out.println("" + + " [!] " + currentLocalizationCode + " → [" + i + "] dates are not equal\n" + + " " + referenceLocalizationCode + ": " + + referenceDateString + " → " + referenceItem.getTextualUploadDate() + + "\n " + currentLocalizationCode + ": " + + currentDateString + " → " + currentItem.getTextualUploadDate()); + } + + } + } + + if (someFail) { + fail("Some localization failed"); + } else { + if (DEBUG) System.out.print("All tests passed" + + "\n\n===============================\n\n"); + } + } +} diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java index 6d22e4d66..6bf76b615 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeCommentsExtractorTest.java @@ -1,23 +1,23 @@ package org.schabi.newpipe.extractor.services.youtube; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.schabi.newpipe.extractor.ServiceList.YouTube; - -import java.io.IOException; -import java.util.List; - import org.jsoup.helper.StringUtil; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.comments.CommentsInfo; import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.services.DefaultTests; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeCommentsExtractor; -import org.schabi.newpipe.extractor.utils.Localization; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.*; +import static org.schabi.newpipe.extractor.ServiceList.YouTube; public class YoutubeCommentsExtractorTest { @@ -25,7 +25,7 @@ public class YoutubeCommentsExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeCommentsExtractor) YouTube .getCommentsExtractor("https://www.youtube.com/watch?v=D00Au7k3i6o"); } @@ -64,6 +64,8 @@ public class YoutubeCommentsExtractorTest { @Test public void testGetCommentsAllData() throws IOException, ExtractionException { InfoItemsPage comments = extractor.getInitialPage(); + + DefaultTests.defaultTestListOfItems(YouTube.getServiceId(), comments.getItems(), comments.getErrors()); for(CommentsInfoItem c: comments.getItems()) { assertFalse(StringUtil.isBlank(c.getAuthorEndpoint())); assertFalse(StringUtil.isBlank(c.getAuthorName())); @@ -71,10 +73,11 @@ public class YoutubeCommentsExtractorTest { assertFalse(StringUtil.isBlank(c.getCommentId())); assertFalse(StringUtil.isBlank(c.getCommentText())); assertFalse(StringUtil.isBlank(c.getName())); - assertFalse(StringUtil.isBlank(c.getPublishedTime())); + assertFalse(StringUtil.isBlank(c.getTextualPublishedTime())); + assertNotNull(c.getPublishedTime()); assertFalse(StringUtil.isBlank(c.getThumbnailUrl())); assertFalse(StringUtil.isBlank(c.getUrl())); - assertFalse(c.getLikeCount() == null); + assertFalse(c.getLikeCount() < 0); } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistExtractorTest.java index 9f3c40490..d4de9175e 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistExtractorTest.java @@ -3,7 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.ServiceList; @@ -12,7 +12,6 @@ import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.services.BasePlaylistExtractorTest; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubePlaylistExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -29,7 +28,7 @@ public class YoutubePlaylistExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubePlaylistExtractor) YouTube .getPlaylistExtractor("http://www.youtube.com/watch?v=lp-EO5I60KA&list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"); extractor.fetchPage(); @@ -126,7 +125,7 @@ public class YoutubePlaylistExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubePlaylistExtractor) YouTube .getPlaylistExtractor("https://www.youtube.com/watch?v=8SbUC-UaAxE&list=PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistLinkHandlerFactoryTest.java index 4e2d148cd..037c09040 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubePlaylistLinkHandlerFactoryTest.java @@ -2,11 +2,10 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.*; @@ -18,8 +17,8 @@ public class YoutubePlaylistLinkHandlerFactoryTest { @BeforeClass public static void setUp() { + NewPipe.init(DownloaderTestImpl.getInstance()); linkHandler = YoutubePlaylistLinkHandlerFactory.getInstance(); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); } @Test(expected = IllegalArgumentException.class) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeServiceTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeServiceTest.java index d90a351c3..6de39e5ce 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeServiceTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeServiceTest.java @@ -22,11 +22,10 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.kiosk.KioskList; -import org.schabi.newpipe.extractor.utils.Localization; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -41,7 +40,7 @@ public class YoutubeServiceTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); service = YouTube; kioskList = service.getKioskList(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamLinkHandlerFactoryTest.java index 154dcdd26..d3f463f3f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamLinkHandlerFactoryTest.java @@ -2,12 +2,11 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.FoundAdException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import java.util.ArrayList; import java.util.List; @@ -24,7 +23,7 @@ public class YoutubeStreamLinkHandlerFactoryTest { @BeforeClass public static void setUp() { linkHandler = YoutubeStreamLinkHandlerFactory.getInstance(); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test(expected = IllegalArgumentException.class) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSubscriptionExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSubscriptionExtractorTest.java index c5739b854..80821d267 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSubscriptionExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSubscriptionExtractorTest.java @@ -2,14 +2,13 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSubscriptionExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.subscription.SubscriptionItem; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.ByteArrayInputStream; import java.io.File; @@ -28,7 +27,7 @@ public class YoutubeSubscriptionExtractorTest { @BeforeClass public static void setupClass() { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); subscriptionExtractor = new YoutubeSubscriptionExtractor(ServiceList.YouTube); urlHandler = ServiceList.YouTube.getChannelLHFactory(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSuggestionExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSuggestionExtractorTest.java index 25d368888..d831eeda5 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSuggestionExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSuggestionExtractorTest.java @@ -22,11 +22,11 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.SuggestionExtractor; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; import java.io.IOException; @@ -41,7 +41,7 @@ public class YoutubeSuggestionExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("DE", "de")); + NewPipe.init(DownloaderTestImpl.getInstance(), new Localization("de", "DE")); suggestionExtractor = YouTube.getSuggestionExtractor(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingExtractorTest.java index 8dee92e09..4931fc509 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingExtractorTest.java @@ -22,13 +22,13 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingExtractor; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Utils; import static junit.framework.TestCase.assertFalse; @@ -46,10 +46,11 @@ public class YoutubeTrendingExtractorTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeTrendingExtractor) YouTube .getKioskList() .getExtractorById("Trending", null); + extractor.forceContentCountry(new ContentCountry("de")); extractor.fetchPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingKioskInfoTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingKioskInfoTest.java index 68a5bae0f..c8e23c06e 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingKioskInfoTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingKioskInfoTest.java @@ -22,12 +22,11 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.kiosk.KioskInfo; -import org.schabi.newpipe.extractor.utils.Localization; +import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -42,7 +41,7 @@ public class YoutubeTrendingKioskInfoTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); StreamingService service = YouTube; LinkHandlerFactory LinkHandlerFactory = service.getKioskList().getListLinkHandlerFactoryByType("Trending"); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingLinkHandlerFactoryTest.java index ddb5550c9..b6b7d54c0 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeTrendingLinkHandlerFactoryTest.java @@ -22,12 +22,11 @@ package org.schabi.newpipe.extractor.services.youtube; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; @@ -43,7 +42,7 @@ public class YoutubeTrendingLinkHandlerFactoryTest { @BeforeClass public static void setUp() throws Exception { LinkHandlerFactory = YouTube.getKioskList().getListLinkHandlerFactoryByType("Trending"); - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java index 35b138e42..c9568045a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java @@ -2,12 +2,11 @@ package org.schabi.newpipe.extractor.services.youtube.search; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static java.util.Collections.singletonList; import static junit.framework.TestCase.assertTrue; @@ -20,9 +19,9 @@ public class YoutubeSearchCountTest { public static class YoutubeChannelViewCountTest extends YoutubeSearchExtractorBaseTest { @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie", - singletonList(YoutubeSearchQueryHandlerFactory.CHANNELS), null, new Localization("GB", "en")); + singletonList(YoutubeSearchQueryHandlerFactory.CHANNELS), null); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorChannelOnlyTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorChannelOnlyTest.java index 1031ce241..12e76a08a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorChannelOnlyTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorChannelOnlyTest.java @@ -4,14 +4,13 @@ import org.hamcrest.CoreMatchers; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; -import org.schabi.newpipe.extractor.utils.Localization; import static java.util.Arrays.asList; import static org.junit.Assert.*; @@ -21,9 +20,9 @@ public class YoutubeSearchExtractorChannelOnlyTest extends YoutubeSearchExtracto @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie", - asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null, new Localization("GB", "en")); + asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); } @@ -31,7 +30,7 @@ public class YoutubeSearchExtractorChannelOnlyTest extends YoutubeSearchExtracto @Test public void testGetSecondPage() throws Exception { YoutubeSearchExtractor secondExtractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie", - asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null, new Localization("GB", "en")); + asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null); ListExtractor.InfoItemsPage secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl()); assertTrue(Integer.toString(secondPage.getItems().size()), secondPage.getItems().size() > 10); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorDefaultTest.java index bef1c6207..49e3520df 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorDefaultTest.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.youtube.search; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; @@ -10,11 +10,8 @@ import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.utils.Localization; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ServiceList.YouTube; /* @@ -44,7 +41,7 @@ public class YoutubeSearchExtractorDefaultTest extends YoutubeSearchExtractorBas @BeforeClass public static void setUpClass() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie"); extractor.fetchPage(); itemsPage = extractor.getInitialPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java index 6a24ec5f2..c626651aa 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java @@ -3,7 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube.stream; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -12,10 +12,13 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.VideoStream; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; import static org.junit.Assert.*; @@ -31,7 +34,7 @@ public class YoutubeStreamExtractorAgeRestrictedTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=MmBeUZqv1QA"); extractor.fetchPage(); @@ -82,8 +85,15 @@ public class YoutubeStreamExtractorAgeRestrictedTest { } @Test - public void testGetUploadDate() throws ParsingException { - assertTrue(extractor.getUploadDate().length() > 0); + public void testGetTextualUploadDate() throws ParsingException { + assertEquals("2017-01-25", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2017-01-25")); + assertEquals(instance, extractor.getUploadDate()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java index 261d521c1..214f6beca 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java @@ -3,7 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube.stream; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -12,10 +12,12 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory; import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.VideoStream; -import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; import static org.junit.Assert.*; @@ -30,7 +32,7 @@ public class YoutubeStreamExtractorControversialTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=T4XJQO3qol8"); extractor.fetchPage(); @@ -82,8 +84,15 @@ public class YoutubeStreamExtractorControversialTest { } @Test - public void testGetUploadDate() throws ParsingException { - assertTrue(extractor.getUploadDate().length() > 0); + public void testGetTextualUploadDate() throws ParsingException { + assertEquals("2010-09-09", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2010-09-09")); + assertEquals(instance, extractor.getUploadDate()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java index a0e5050ab..27638efe9 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java @@ -1,8 +1,9 @@ package org.schabi.newpipe.extractor.services.youtube.stream; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.ExtractorAsserts; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; @@ -10,10 +11,13 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.stream.*; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Utils; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; import java.util.List; import static org.junit.Assert.*; @@ -53,7 +57,7 @@ public class YoutubeStreamExtractorDefaultTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=YQHsXMglC9A"); extractor.fetchPage(); @@ -107,8 +111,15 @@ public class YoutubeStreamExtractorDefaultTest { } @Test - public void testGetUploadDate() throws ParsingException { - assertTrue(extractor.getUploadDate().length() > 0); + public void testGetTextualUploadDate() throws ParsingException { + Assert.assertEquals("2015-10-22", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2015-10-22")); + Assert.assertEquals(instance, extractor.getUploadDate()); } @Test @@ -179,7 +190,7 @@ public class YoutubeStreamExtractorDefaultTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=fBc4Q_htqPg"); extractor.fetchPage(); @@ -208,7 +219,7 @@ public class YoutubeStreamExtractorDefaultTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=cV5TjZCJkuA"); extractor.fetchPage(); @@ -239,7 +250,7 @@ public class YoutubeStreamExtractorDefaultTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=HoK9shIJ2xQ"); extractor.fetchPage(); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java index 3e24b7e36..408c29a3f 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java @@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.youtube.stream; import org.junit.BeforeClass; import org.junit.Test; -import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -11,7 +11,6 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExt import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.VideoStream; -import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.extractor.utils.Utils; import java.io.IOException; @@ -25,7 +24,7 @@ public class YoutubeStreamExtractorLivestreamTest { @BeforeClass public static void setUp() throws Exception { - NewPipe.init(Downloader.getInstance(), new Localization("GB", "en")); + NewPipe.init(DownloaderTestImpl.getInstance()); extractor = (YoutubeStreamExtractor) YouTube .getStreamExtractor("https://www.youtube.com/watch?v=EcEMX-63PKY"); extractor.fetchPage(); @@ -74,7 +73,8 @@ public class YoutubeStreamExtractorLivestreamTest { @Test public void testGetUploadDate() throws ParsingException { - assertTrue(extractor.getUploadDate().length() > 0); + assertNull(extractor.getUploadDate()); + assertNull(extractor.getTextualUploadDate()); } @Test diff --git a/timeago-parser/build.gradle b/timeago-parser/build.gradle index 8c94acb92..bd99b48bb 100644 --- a/timeago-parser/build.gradle +++ b/timeago-parser/build.gradle @@ -1,3 +1,6 @@ dependencies { testImplementation 'junit:junit:4.12' + + implementation 'com.grack:nanojson:1.1' + implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0' } \ No newline at end of file diff --git a/timeago-parser/raw/java/GeneratePatternClasses.java b/timeago-parser/raw/java/GeneratePatternClasses.java new file mode 100644 index 000000000..cb395c7df --- /dev/null +++ b/timeago-parser/raw/java/GeneratePatternClasses.java @@ -0,0 +1,116 @@ +import com.grack.nanojson.JsonArray; +import com.grack.nanojson.JsonObject; +import com.grack.nanojson.JsonParser; +import com.grack.nanojson.JsonParserException; +import org.schabi.newpipe.extractor.timeago.PatternsHolder; +import org.schabi.newpipe.extractor.timeago.TimeAgoUnit; + +import java.io.*; +import java.util.*; + +public class GeneratePatternClasses { + public static void main(String[] args) throws FileNotFoundException, JsonParserException { + final InputStream resourceAsStream = + new FileInputStream("timeago-parser/raw/unique_patterns.json"); + + final JsonObject from = JsonParser.object().from(resourceAsStream); + final TreeMap map = new TreeMap<>(from); + + for (Map.Entry entry : map.entrySet()) { + final String languageCode = entry.getKey().replace('-', '_'); + final Map unitsList = (Map) entry.getValue(); + + final String wordSeparator = (String) unitsList.get("word_separator"); + + final JsonArray seconds = (JsonArray) unitsList.get("seconds"); + final JsonArray minutes = (JsonArray) unitsList.get("minutes"); + final JsonArray hours = (JsonArray) unitsList.get("hours"); + final JsonArray days = (JsonArray) unitsList.get("days"); + final JsonArray weeks = (JsonArray) unitsList.get("weeks"); + final JsonArray months = (JsonArray) unitsList.get("months"); + final JsonArray years = (JsonArray) unitsList.get("years"); + + final StringBuilder specialCasesString = new StringBuilder(); + specialCasesConstruct(TimeAgoUnit.SECONDS, seconds, specialCasesString); + specialCasesConstruct(TimeAgoUnit.MINUTES, minutes, specialCasesString); + specialCasesConstruct(TimeAgoUnit.HOURS, hours, specialCasesString); + specialCasesConstruct(TimeAgoUnit.DAYS, days, specialCasesString); + specialCasesConstruct(TimeAgoUnit.WEEKS, weeks, specialCasesString); + specialCasesConstruct(TimeAgoUnit.MONTHS, months, specialCasesString); + specialCasesConstruct(TimeAgoUnit.YEARS, years, specialCasesString); + + System.out.println("Generating \"" + languageCode + "\" pattern class..."); + + try (final FileWriter fileOut = new FileWriter( + "timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/" + + languageCode + ".java")) { + final String test = INFO_CLASS_GENERATED + "\n" + + "\n" + + "package org.schabi.newpipe.extractor.timeago.patterns;\n\n" + + "import org.schabi.newpipe.extractor.timeago.PatternsHolder;\n" + + (specialCasesString.length() > 0 ? "import org.schabi.newpipe.extractor.timeago.TimeAgoUnit;\n" : "") + + "\n" + + "public class " + languageCode + " extends PatternsHolder {\n" + + " private static final String WORD_SEPARATOR = \"" + wordSeparator + "\";\n" + + " private static final String[]\n" + + " SECONDS /**/ = {" + join(seconds) + "},\n" + + " MINUTES /**/ = {" + join(minutes) + "},\n" + + " HOURS /**/ = {" + join(hours) + "},\n" + + " DAYS /**/ = {" + join(days) + "},\n" + + " WEEKS /**/ = {" + join(weeks) + "},\n" + + " MONTHS /**/ = {" + join(months) + "},\n" + + " YEARS /**/ = {" + join(years) + "};\n" + + "\n" + + " private static final " + languageCode + " INSTANCE = new " + languageCode + "();\n" + + "\n" + + " public static " + languageCode + " getInstance() {\n" + + " return INSTANCE;\n" + + " }\n" + + "\n" + + " private " + languageCode + "() {\n" + + " super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS);\n" + + specialCasesString.toString() + + " }\n" + + "}"; + fileOut.write(test); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static void specialCasesConstruct(TimeAgoUnit unit, JsonArray array, StringBuilder stringBuilder) { + final Iterator iterator = array.iterator(); + while (iterator.hasNext()) { + final Object o = iterator.next(); + if (o instanceof JsonObject) { + final JsonObject caseObject = (JsonObject) o; + for (Map.Entry caseEntry : caseObject.entrySet()) { + final int caseAmount = Integer.parseInt(caseEntry.getKey()); + final String caseText = (String) caseEntry.getValue(); + iterator.remove(); + + stringBuilder.append(" ") + .append("putSpecialCase(TimeAgoUnit.").append(unit.name()) + .append(", \"").append(caseText).append("\"") + .append(", ").append(caseAmount).append(");").append("\n"); + } + } + } + } + + private static final String INFO_CLASS_GENERATED = "/**/// DO NOT MODIFY THIS FILE MANUALLY\n" + + "/**/// This class was automatically generated by \"GeneratePatternClasses.java\",\n" + + "/**/// modify the \"unique_patterns.json\" and re-generate instead."; + + private static String join(List list) { + final StringBuilder toReturn = new StringBuilder(); + + for (Object o : list) { + toReturn.append('"').append(o).append('"').append(", "); + } + toReturn.setLength(Math.max(toReturn.length() - 2, 0)); + + return toReturn.toString(); + } +} \ No newline at end of file diff --git a/timeago-parser/raw/java/GenerateResourceBundles.java b/timeago-parser/raw/java/GenerateResourceBundles.java deleted file mode 100644 index b2b818c1e..000000000 --- a/timeago-parser/raw/java/GenerateResourceBundles.java +++ /dev/null @@ -1,59 +0,0 @@ -import com.grack.nanojson.JsonArray; -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import static org.schabi.newpipe.extractor.timeago.TimeAgoPatternsManager.RESOURCE_BUNDLE_ARRAY_SEPARATOR; - -public class GenerateResourceBundles { - - public static void main(String[] args) throws Exception { - File outDir = new File("timeago-parser/outBundle"); - if (!outDir.isDirectory()) outDir.mkdir(); - - JsonObject object = JsonParser.object().from(new FileInputStream(new File("timeago-parser/raw/unique_patterns.json"))); - - for (Map.Entry langTimeEntry : new TreeMap<>(object).entrySet()) { - final String langName = langTimeEntry.getKey(); - StringBuilder outString = new StringBuilder(); - - final TreeMap sortedMap = new TreeMap<>(Utils.compareByUnitName()); - sortedMap.putAll((JsonObject) langTimeEntry.getValue()); - - final Iterator> unitEntriesIterator = sortedMap.entrySet().iterator(); - while (unitEntriesIterator.hasNext()) { - final Map.Entry unitEntry = unitEntriesIterator.next(); - final String unitName = unitEntry.getKey(); - final List unitList = (JsonArray) unitEntry.getValue(); - - outString.append(unitName).append("=\\\n"); - - for (int i = 0; i < unitList.size(); i++) { - final String s = unitList.get(i).toString(); - outString.append(" ").append(s); - - if (i < unitList.size() - 1) { - outString.append(RESOURCE_BUNDLE_ARRAY_SEPARATOR).append("\\").append("\n"); - } - } - - if (unitEntriesIterator.hasNext()) outString.append("\n\n"); - } - - String fileName = "time_units_" + langName.replaceAll("-", "_") + ".properties"; - System.out.println("Writing " + fileName + "..."); - try (OutputStream out = new FileOutputStream(new File(outDir, fileName))) { - out.write(outString.toString().getBytes("UTF-8")); - } - } - - } -} diff --git a/timeago-parser/raw/unique_patterns.json b/timeago-parser/raw/unique_patterns.json index 58e21182b..1d9253828 100644 --- a/timeago-parser/raw/unique_patterns.json +++ b/timeago-parser/raw/unique_patterns.json @@ -1,5 +1,6 @@ { "af": { + "word_separator": " ", "seconds": [ "sekonde", "sekondes" @@ -29,6 +30,7 @@ ] }, "am": { + "word_separator": " ", "seconds": [ "ሰኮንዶች", "ሴኮንድ" @@ -59,6 +61,7 @@ ] }, "ar": { + "word_separator": " ", "seconds": [ "ثانية", "ثانيتين", @@ -97,6 +100,7 @@ ] }, "az": { + "word_separator": " ", "seconds": [ "saniyə" ], @@ -120,37 +124,48 @@ ] }, "be": { + "word_separator": " ", "seconds": [ "секунд", "секунду", "секунды" ], "minutes": [ + "хвілін", "хвіліну", "хвіліны" ], "hours": [ + "гадзін", "гадзіну", "гадзіны" ], "days": [ "дзень", - "дня" + "дзён", + "дня", + "дні" ], "weeks": [ "тыдзень", - "тыдня" + "тыдня", + "тыдні" ], "months": [ "месяц", - "месяца" + "месяца", + "месяцы", + "месяцаў" ], "years": [ "год", - "года" + "года", + "гады", + "гадоў" ] }, "bg": { + "word_separator": " ", "seconds": [ "секунда", "секунди" @@ -181,6 +196,7 @@ ] }, "bn": { + "word_separator": " ", "seconds": [ "সেকেন্ড" ], @@ -204,17 +220,22 @@ ] }, "bs": { + "word_separator": " ", "seconds": [ "sekundi", + "sekunde", "sekundu" ], "minutes": [ "minuta", + "minute", "minutu" ], "hours": [ "h", - "sat" + "sat", + "sata", + "sati" ], "days": [ "dan", @@ -225,15 +246,18 @@ ], "months": [ "mj.", - "mjesec" + "mjesec", + "mjeseca", + "mjeseci" ], "years": [ - "godine", "godina", + "godine", "godinu" ] }, "ca": { + "word_separator": " ", "seconds": [ "segon", "segons" @@ -264,6 +288,7 @@ ] }, "cs": { + "word_separator": " ", "seconds": [ "sekundami", "sekundou" @@ -290,10 +315,12 @@ ], "years": [ "rokem", - "roky" + "roky", + "lety" ] }, "da": { + "word_separator": " ", "seconds": [ "sekund", "sekunder" @@ -323,6 +350,7 @@ ] }, "de": { + "word_separator": " ", "seconds": [ "Sekunde", "Sekunden" @@ -353,6 +381,7 @@ ] }, "el": { + "word_separator": " ", "seconds": [ "δευτερόλεπτα", "δευτερόλεπτο" @@ -383,6 +412,7 @@ ] }, "en": { + "word_separator": " ", "seconds": [ "second", "seconds" @@ -413,6 +443,7 @@ ] }, "en-GB": { + "word_separator": " ", "seconds": [ "second", "seconds" @@ -443,6 +474,7 @@ ] }, "es": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -473,6 +505,7 @@ ] }, "es-419": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -503,6 +536,7 @@ ] }, "es-US": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -533,6 +567,7 @@ ] }, "et": { + "word_separator": " ", "seconds": [ "sekund", "sekundit" @@ -563,6 +598,7 @@ ] }, "eu": { + "word_separator": " ", "seconds": [ "segundo" ], @@ -589,6 +625,7 @@ ] }, "fa": { + "word_separator": " ", "seconds": [ "ثانیه" ], @@ -612,6 +649,7 @@ ] }, "fi": { + "word_separator": " ", "seconds": [ "sekunti", "sekuntia" @@ -642,6 +680,7 @@ ] }, "fil": { + "word_separator": " ", "seconds": [ "segundo" ], @@ -665,6 +704,7 @@ ] }, "fr": { + "word_separator": " ", "seconds": [ "seconde", "secondes" @@ -694,6 +734,7 @@ ] }, "fr-CA": { + "word_separator": " ", "seconds": [ "seconde", "secondes" @@ -723,6 +764,7 @@ ] }, "gl": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -753,6 +795,7 @@ ] }, "gu": { + "word_separator": " ", "seconds": [ "સેકંડ" ], @@ -776,6 +819,7 @@ ] }, "hi": { + "word_separator": " ", "seconds": [ "सेकंड" ], @@ -790,7 +834,8 @@ "दिन" ], "weeks": [ - "सप्ताह" + "सप्ताह", + "हफ़्ते" ], "months": [ "महीना", @@ -801,6 +846,7 @@ ] }, "hr": { + "word_separator": " ", "seconds": [ "sekunde", "sekundi", @@ -836,6 +882,7 @@ ] }, "hu": { + "word_separator": " ", "seconds": [ "másodperce" ], @@ -859,6 +906,7 @@ ] }, "hy": { + "word_separator": " ", "seconds": [ "վայրկյան" ], @@ -882,6 +930,7 @@ ] }, "id": { + "word_separator": " ", "seconds": [ "detik" ], @@ -905,25 +954,41 @@ ] }, "is": { + "word_separator": " ", "seconds": [ "sekúndu", - "sekúndum" + "sekúndum", + + "second", + "seconds" ], "minutes": [ "mínútu", - "mínútum" + "mínútum", + + "minute", + "minutes" ], "hours": [ "klukkustund", - "klukkustundum" + "klukkustundum", + + "hour", + "hours" ], "days": [ "degi", - "dögum" + "dögum", + + "day", + "days" ], "weeks": [ "viku", - "vikum" + "vikum", + + "week", + "weeks" ], "months": [ "mánuði", @@ -935,6 +1000,7 @@ ] }, "it": { + "word_separator": " ", "seconds": [ "secondi", "secondo" @@ -965,6 +1031,7 @@ ] }, "iw": { + "word_separator": " ", "seconds": [ "שניות", "שנייה" @@ -975,26 +1042,42 @@ ], "hours": [ "שעה", - "שעות" + "שעות", + { + "2": "שעתיים" + } ], "days": [ "יום", - "ימים" + "ימים", + { + "2": "יומיים" + } ], "weeks": [ "שבוע", - "שבועות" + "שבועות", + { + "2": "שבועיים" + } ], "months": [ "חודש", - "חודשים" + "חודשים", + { + "2": "חודשיים" + } ], "years": [ "שנה", - "שנים" + "שנים", + { + "2": "שנתיים" + } ] }, "ja": { + "word_separator": "", "seconds": [ "秒前" ], @@ -1018,6 +1101,7 @@ ] }, "ka": { + "word_separator": " ", "seconds": [ "წამის" ], @@ -1041,6 +1125,7 @@ ] }, "kk": { + "word_separator": " ", "seconds": [ "секунд" ], @@ -1064,6 +1149,7 @@ ] }, "km": { + "word_separator": "", "seconds": [ "វិនាទី\u200bមុន", "១វិនាទីមុន" @@ -1094,6 +1180,7 @@ ] }, "kn": { + "word_separator": " ", "seconds": [ "ಸೆಕೆಂಡುಗಳ", "ಸೆಕೆಂಡ್" @@ -1124,6 +1211,7 @@ ] }, "ko": { + "word_separator": "", "seconds": [ "초" ], @@ -1147,6 +1235,7 @@ ] }, "ky": { + "word_separator": " ", "seconds": [ "секунд" ], @@ -1170,6 +1259,7 @@ ] }, "lo": { + "word_separator": "", "seconds": [ "ວິນາທີກ່ອນນີ້" ], @@ -1194,6 +1284,7 @@ ] }, "lt": { + "word_separator": " ", "seconds": [ "sekundes", "sekundę", @@ -1228,6 +1319,7 @@ ] }, "lv": { + "word_separator": " ", "seconds": [ "sekundes", "sekundēm" @@ -1259,6 +1351,7 @@ ] }, "mk": { + "word_separator": " ", "seconds": [ "секунда", "секунди" @@ -1289,6 +1382,7 @@ ] }, "ml": { + "word_separator": "", "seconds": [ "സെക്കന്റ്", "സെക്കൻഡ്" @@ -1314,6 +1408,7 @@ ] }, "mn": { + "word_separator": " ", "seconds": [ "секундын" ], @@ -1338,6 +1433,7 @@ ] }, "mr": { + "word_separator": "", "seconds": [ "सेकंदांपूर्वी", "सेकंदापूर्वी" @@ -1368,6 +1464,7 @@ ] }, "ms": { + "word_separator": " ", "seconds": [ "saat" ], @@ -1391,6 +1488,7 @@ ] }, "my": { + "word_separator": " ", "seconds": [ "စက္ကန့်" ], @@ -1414,6 +1512,7 @@ ] }, "ne": { + "word_separator": " ", "seconds": [ "सेकेन्ड" ], @@ -1437,6 +1536,7 @@ ] }, "nl": { + "word_separator": " ", "seconds": [ "seconde", "seconden" @@ -1465,6 +1565,7 @@ ] }, "no": { + "word_separator": " ", "seconds": [ "sekund", "sekunder" @@ -1493,6 +1594,7 @@ ] }, "pa": { + "word_separator": " ", "seconds": [ "ਸਕਿੰਟ" ], @@ -1519,6 +1621,7 @@ ] }, "pl": { + "word_separator": " ", "seconds": [ "sekund", "sekundy", @@ -1554,6 +1657,7 @@ ] }, "pt": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -1584,6 +1688,7 @@ ] }, "pt-PT": { + "word_separator": " ", "seconds": [ "segundo", "segundos" @@ -1614,6 +1719,7 @@ ] }, "ro": { + "word_separator": " ", "seconds": [ "secunde", "secundă" @@ -1644,6 +1750,7 @@ ] }, "ru": { + "word_separator": " ", "seconds": [ "секунд", "секунду", @@ -1681,6 +1788,7 @@ ] }, "si": { + "word_separator": " ", "seconds": [ "තත්පර" ], @@ -1704,6 +1812,7 @@ ] }, "sk": { + "word_separator": " ", "seconds": [ "sekundami", "sekundou" @@ -1734,6 +1843,7 @@ ] }, "sl": { + "word_separator": " ", "seconds": [ "sekundama", "sekundami", @@ -1771,6 +1881,7 @@ ] }, "sq": { + "word_separator": " ", "seconds": [ "sekonda", "sekondë" @@ -1797,6 +1908,7 @@ ] }, "sr": { + "word_separator": " ", "seconds": [ "секунде", "секунди" @@ -1810,8 +1922,12 @@ "сати" ], "days": [ - "дан", - "дана" + "Пре 1 дан", + "Пре 2 дана", + "Пре 3 дана", + "Пре 4 дана", + "Пре 5 дана", + "Пре 6 дана" ], "weeks": [ "недеље", @@ -1829,6 +1945,7 @@ ] }, "sr-Latn": { + "word_separator": " ", "seconds": [ "sekunde", "sekundi" @@ -1838,11 +1955,16 @@ ], "hours": [ "sat", - "sati" + "sati", + "sata" ], "days": [ - "dan", - "dana" + "Pre 1 dan", + "Pre 2 dana", + "Pre 3 dana", + "Pre 4 dana", + "Pre 5 dana", + "Pre 6 dana" ], "weeks": [ "nedelja", @@ -1861,6 +1983,7 @@ ] }, "sv": { + "word_separator": " ", "seconds": [ "sekund", "sekunder" @@ -1890,6 +2013,7 @@ ] }, "sw": { + "word_separator": " ", "seconds": [ "sekunde" ], @@ -1915,6 +2039,7 @@ ] }, "ta": { + "word_separator": " ", "seconds": [ "வினாடி", "வினாடிகளுக்கு" @@ -1944,6 +2069,7 @@ ] }, "te": { + "word_separator": " ", "seconds": [ "సెకను", "సెకన్ల" @@ -1974,6 +2100,7 @@ ] }, "th": { + "word_separator": "", "seconds": [ "วินาทีที่ผ่านมา" ], @@ -1997,6 +2124,7 @@ ] }, "tr": { + "word_separator": " ", "seconds": [ "saniye" ], @@ -2020,6 +2148,7 @@ ] }, "uk": { + "word_separator": " ", "seconds": [ "секунд", "секунди", @@ -2056,6 +2185,7 @@ ] }, "ur": { + "word_separator": " ", "seconds": [ "سیکنڈ", "سیکنڈز" @@ -2083,6 +2213,7 @@ ] }, "uz": { + "word_separator": " ", "seconds": [ "soniya" ], @@ -2106,6 +2237,7 @@ ] }, "vi": { + "word_separator": " ", "seconds": [ "giây" ], @@ -2113,7 +2245,8 @@ "phút" ], "hours": [ - "giờ" + "giờ", + "tiếng" ], "days": [ "ngày" @@ -2129,6 +2262,7 @@ ] }, "zh-CN": { + "word_separator": "", "seconds": [ "秒前" ], @@ -2152,6 +2286,7 @@ ] }, "zh-HK": { + "word_separator": "", "seconds": [ "秒前" ], @@ -2175,6 +2310,7 @@ ] }, "zh-TW": { + "word_separator": "", "seconds": [ "秒前" ], @@ -2198,6 +2334,7 @@ ] }, "zu": { + "word_separator": " ", "seconds": [ "amasekhondi", "isekhondi" diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsHolder.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsHolder.java new file mode 100644 index 000000000..91f931025 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsHolder.java @@ -0,0 +1,99 @@ +package org.schabi.newpipe.extractor.timeago; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import static java.util.Arrays.asList; + +public abstract class PatternsHolder { + private final String wordSeparator; + private final Collection seconds; + private final Collection minutes; + private final Collection hours; + private final Collection days; + private final Collection weeks; + private final Collection months; + private final Collection years; + + private final Map> specialCases = new LinkedHashMap<>(); + + protected PatternsHolder(String wordSeparator, Collection seconds, Collection minutes, + Collection hours, Collection days, + Collection weeks, Collection months, Collection years) { + this.wordSeparator = wordSeparator; + this.seconds = seconds; + this.minutes = minutes; + this.hours = hours; + this.days = days; + this.weeks = weeks; + this.months = months; + this.years = years; + } + + protected PatternsHolder(String wordSeparator, String[] seconds, String[] minutes, String[] hours, String[] days, + String[] weeks, String[] months, String[] years) { + this(wordSeparator, asList(seconds), asList(minutes), asList(hours), asList(days), + asList(weeks), asList(months), asList(years)); + } + + public String wordSeparator() { + return wordSeparator; + } + + public Collection seconds() { + return seconds; + } + + public Collection minutes() { + return minutes; + } + + public Collection hours() { + return hours; + } + + public Collection days() { + return days; + } + + public Collection weeks() { + return weeks; + } + + public Collection months() { + return months; + } + + public Collection years() { + return years; + } + + public Map> specialCases() { + return specialCases; + } + + protected void putSpecialCase(TimeAgoUnit unit, String caseText, int caseAmount) { + Map item = specialCases.get(unit); + + if (item == null) { + item = new LinkedHashMap<>(); + specialCases.put(unit, item); + } + + item.put(caseText, caseAmount); + } + + public Map> asMap() { + final Map> returnMap = new LinkedHashMap<>(); + returnMap.put(TimeAgoUnit.SECONDS, seconds()); + returnMap.put(TimeAgoUnit.MINUTES, minutes()); + returnMap.put(TimeAgoUnit.HOURS, hours()); + returnMap.put(TimeAgoUnit.DAYS, days()); + returnMap.put(TimeAgoUnit.WEEKS, weeks()); + returnMap.put(TimeAgoUnit.MONTHS, months()); + returnMap.put(TimeAgoUnit.YEARS, years()); + + return returnMap; + } +} diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsManager.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsManager.java new file mode 100644 index 000000000..22f939166 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/PatternsManager.java @@ -0,0 +1,31 @@ +package org.schabi.newpipe.extractor.timeago; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; + +public class PatternsManager { + /** + * Return an holder object containing all the patterns array. + * + * @return an object containing the patterns. If not existent, {@code null}. + */ + @Nullable + public static PatternsHolder getPatterns(@Nonnull String languageCode, @Nullable String countryCode) { + final String targetLocalizationClassName = languageCode + + (countryCode == null || countryCode.isEmpty() ? "" : "_" + countryCode); + + try { + final Class targetClass = Class.forName( + "org.schabi.newpipe.extractor.timeago.patterns." + targetLocalizationClassName); + + return (PatternsHolder) targetClass.getDeclaredMethod("getInstance").invoke(null); + } catch (ClassNotFoundException ignored) { + // Target localization is not supported + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + + return null; + } +} diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/ResourceBundleUTF8.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/ResourceBundleUTF8.java deleted file mode 100644 index 0a084f72e..000000000 --- a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/ResourceBundleUTF8.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.schabi.newpipe.extractor.timeago; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.Locale; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; - -/** - * Handy class to get normal UTF-8 strings from the resource bundles. - */ -public class ResourceBundleUTF8 { - private static final UTF8Control utf8Control = new UTF8Control(); - - /** - * @see ResourceBundle#getBundle(String) - */ - public static ResourceBundle getBundle(String baseName) { - return ResourceBundle.getBundle(baseName, utf8Control); - } - - /** - * @see ResourceBundle#getBundle(String, Locale) - */ - public static ResourceBundle getBundle(String baseName, Locale locale) { - return ResourceBundle.getBundle(baseName, locale, utf8Control); - } - - /** - * Class copied from the java source modified to work with UTF-8 strings. - */ - public static class UTF8Control extends ResourceBundle.Control { - @Override - public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { - // COPY FROM SOURCE - - String bundleName = toBundleName(baseName, locale); - ResourceBundle bundle = null; - if (format.equals("java.class")) { - try { - @SuppressWarnings("unchecked") - Class bundleClass - = (Class) loader.loadClass(bundleName); - - // If the class isn't a ResourceBundle subclass, throw a - // ClassCastException. - if (ResourceBundle.class.isAssignableFrom(bundleClass)) { - bundle = bundleClass.newInstance(); - } else { - throw new ClassCastException(bundleClass.getName() - + " cannot be cast to ResourceBundle"); - } - } catch (ClassNotFoundException e) { - } - } else if (format.equals("java.properties")) { - final String resourceName = bundleName.contains("://") ? null : toResourceName(bundleName, "properties"); - if (resourceName == null) { - return bundle; - } - final ClassLoader classLoader = loader; - final boolean reloadFlag = reload; - InputStream stream = null; - try { - stream = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public InputStream run() throws IOException { - InputStream is = null; - if (reloadFlag) { - URL url = classLoader.getResource(resourceName); - if (url != null) { - URLConnection connection = url.openConnection(); - if (connection != null) { - // Disable caches to get fresh data for - // reloading. - connection.setUseCaches(false); - is = connection.getInputStream(); - } - } - } else { - is = classLoader.getResourceAsStream(resourceName); - } - return is; - } - }); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } - if (stream != null) { - try { - ////// Line changed to support UTF-8 - bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); - } finally { - stream.close(); - } - } - } else { - throw new IllegalArgumentException("unknown format: " + format); - } - return bundle; - } - } -} diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoPatternsManager.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoPatternsManager.java deleted file mode 100644 index 4519dcbdc..000000000 --- a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoPatternsManager.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.schabi.newpipe.extractor.timeago; - -public class TimeAgoPatternsManager { - public static final String RESOURCE_BUNDLE_ARRAY_SEPARATOR = "»»"; - // TODO: Uncomment this -/* - /** - * Get an array of patterns from the resources bundle according to the given {@link Locale}. - *

- * It already handles the string/array separator from the resources, as the normal resource - * bundle don't really support an array in the properties file. - *

- * - * @param timeUnit which time unit to get the patterns array - * @param locale locale used to get the localized patterns - * @return an array of phrases localized according to the given locale. - *//* - public static String[] getPatternsArray(TimeUnit timeUnit, Locale locale) { - return ResourceBundleUTF8.getBundle("i18n.time_units", locale).getString(timeUnit.name().toLowerCase()) - .split(RESOURCE_BUNDLE_ARRAY_SEPARATOR); - }*/ - - // public static Map getAllPatternsFor(Locale locale) -} diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoUnit.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoUnit.java new file mode 100644 index 000000000..16e05c243 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/TimeAgoUnit.java @@ -0,0 +1,11 @@ +package org.schabi.newpipe.extractor.timeago; + +public enum TimeAgoUnit { + SECONDS, + MINUTES, + HOURS, + DAYS, + WEEKS, + MONTHS, + YEARS +} diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/af.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/af.java new file mode 100644 index 000000000..245c3e155 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/af.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class af extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekonde", "sekondes"}, + MINUTES /**/ = {"minute", "minuut"}, + HOURS /**/ = {"ure", "uur"}, + DAYS /**/ = {"dae", "dag"}, + WEEKS /**/ = {"week", "weke"}, + MONTHS /**/ = {"maand", "maande"}, + YEARS /**/ = {"jaar"}; + + private static final af INSTANCE = new af(); + + public static af getInstance() { + return INSTANCE; + } + + private af() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/am.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/am.java new file mode 100644 index 000000000..feb709c86 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/am.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class am extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"ሰኮንዶች", "ሴኮንድ"}, + MINUTES /**/ = {"ደቂቃ", "ደቂቃዎች"}, + HOURS /**/ = {"ሰዓት", "ሰዓቶች"}, + DAYS /**/ = {"ቀን", "ቀኖች"}, + WEEKS /**/ = {"ሳምንታት", "ሳምንት"}, + MONTHS /**/ = {"ወራት", "ወር"}, + YEARS /**/ = {"ዓመታት", "ዓመት"}; + + private static final am INSTANCE = new am(); + + public static am getInstance() { + return INSTANCE; + } + + private am() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ar.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ar.java new file mode 100644 index 000000000..95b741cd6 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ar.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ar extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"ثانية", "ثانيتين", "ثوانٍ"}, + MINUTES /**/ = {"دقائق", "دقيقة", "دقيقتين"}, + HOURS /**/ = {"ساعات", "ساعة", "ساعتين"}, + DAYS /**/ = {"أيام", "يوم", "يومين"}, + WEEKS /**/ = {"أسابيع", "أسبوع", "أسبوعين"}, + MONTHS /**/ = {"أشهر", "شهر", "شهرين", "شهرًا"}, + YEARS /**/ = {"سنة", "سنتين", "سنوات"}; + + private static final ar INSTANCE = new ar(); + + public static ar getInstance() { + return INSTANCE; + } + + private ar() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/az.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/az.java new file mode 100644 index 000000000..ee67d474f --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/az.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class az extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"saniyə"}, + MINUTES /**/ = {"dəqiqə"}, + HOURS /**/ = {"saat"}, + DAYS /**/ = {"gün"}, + WEEKS /**/ = {"həftə"}, + MONTHS /**/ = {"ay"}, + YEARS /**/ = {"il"}; + + private static final az INSTANCE = new az(); + + public static az getInstance() { + return INSTANCE; + } + + private az() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/be.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/be.java new file mode 100644 index 000000000..d761f8e80 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/be.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class be extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунд", "секунду", "секунды"}, + MINUTES /**/ = {"хвілін", "хвіліну", "хвіліны"}, + HOURS /**/ = {"гадзін", "гадзіну", "гадзіны"}, + DAYS /**/ = {"дзень", "дзён", "дня", "дні"}, + WEEKS /**/ = {"тыдзень", "тыдня", "тыдні"}, + MONTHS /**/ = {"месяц", "месяца", "месяцы", "месяцаў"}, + YEARS /**/ = {"год", "года", "гады", "гадоў"}; + + private static final be INSTANCE = new be(); + + public static be getInstance() { + return INSTANCE; + } + + private be() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bg.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bg.java new file mode 100644 index 000000000..9d02c3440 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bg.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class bg extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунда", "секунди"}, + MINUTES /**/ = {"минута", "минути"}, + HOURS /**/ = {"час", "часа"}, + DAYS /**/ = {"ден", "дни"}, + WEEKS /**/ = {"седмица", "седмици"}, + MONTHS /**/ = {"месец", "месеца"}, + YEARS /**/ = {"година", "години"}; + + private static final bg INSTANCE = new bg(); + + public static bg getInstance() { + return INSTANCE; + } + + private bg() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bn.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bn.java new file mode 100644 index 000000000..3c19c66a7 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bn.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class bn extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"সেকেন্ড"}, + MINUTES /**/ = {"মিনিট"}, + HOURS /**/ = {"ঘণ্টা"}, + DAYS /**/ = {"দিন"}, + WEEKS /**/ = {"সপ্তাহ"}, + MONTHS /**/ = {"মাস"}, + YEARS /**/ = {"বছর"}; + + private static final bn INSTANCE = new bn(); + + public static bn getInstance() { + return INSTANCE; + } + + private bn() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bs.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bs.java new file mode 100644 index 000000000..735557e46 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/bs.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class bs extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundi", "sekunde", "sekundu"}, + MINUTES /**/ = {"minuta", "minute", "minutu"}, + HOURS /**/ = {"h", "sat", "sata", "sati"}, + DAYS /**/ = {"dan", "dana"}, + WEEKS /**/ = {"sedm."}, + MONTHS /**/ = {"mj.", "mjesec", "mjeseca", "mjeseci"}, + YEARS /**/ = {"godina", "godine", "godinu"}; + + private static final bs INSTANCE = new bs(); + + public static bs getInstance() { + return INSTANCE; + } + + private bs() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ca.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ca.java new file mode 100644 index 000000000..2a432bc64 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ca.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ca extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segon", "segons"}, + MINUTES /**/ = {"minut", "minuts"}, + HOURS /**/ = {"hora", "hores"}, + DAYS /**/ = {"dia", "dies"}, + WEEKS /**/ = {"setmana", "setmanes"}, + MONTHS /**/ = {"mes", "mesos"}, + YEARS /**/ = {"any", "anys"}; + + private static final ca INSTANCE = new ca(); + + public static ca getInstance() { + return INSTANCE; + } + + private ca() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/cs.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/cs.java new file mode 100644 index 000000000..bbb3660c0 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/cs.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class cs extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundami", "sekundou"}, + MINUTES /**/ = {"minutami", "minutou"}, + HOURS /**/ = {"hodinami", "hodinou"}, + DAYS /**/ = {"dny", "včera"}, + WEEKS /**/ = {"týdnem", "týdny"}, + MONTHS /**/ = {"měsícem", "měsíci"}, + YEARS /**/ = {"rokem", "roky", "lety"}; + + private static final cs INSTANCE = new cs(); + + public static cs getInstance() { + return INSTANCE; + } + + private cs() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/da.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/da.java new file mode 100644 index 000000000..da798481c --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/da.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class da extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekund", "sekunder"}, + MINUTES /**/ = {"minut", "minutter"}, + HOURS /**/ = {"time", "timer"}, + DAYS /**/ = {"dag", "dage"}, + WEEKS /**/ = {"uge", "uger"}, + MONTHS /**/ = {"måned", "måneder"}, + YEARS /**/ = {"år"}; + + private static final da INSTANCE = new da(); + + public static da getInstance() { + return INSTANCE; + } + + private da() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/de.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/de.java new file mode 100644 index 000000000..65888f334 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/de.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class de extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"Sekunde", "Sekunden"}, + MINUTES /**/ = {"Minute", "Minuten"}, + HOURS /**/ = {"Stunde", "Stunden"}, + DAYS /**/ = {"Tag", "Tagen"}, + WEEKS /**/ = {"Woche", "Wochen"}, + MONTHS /**/ = {"Monat", "Monaten"}, + YEARS /**/ = {"Jahr", "Jahren"}; + + private static final de INSTANCE = new de(); + + public static de getInstance() { + return INSTANCE; + } + + private de() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/el.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/el.java new file mode 100644 index 000000000..61a071e0a --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/el.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class el extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"δευτερόλεπτα", "δευτερόλεπτο"}, + MINUTES /**/ = {"λεπτά", "λεπτό"}, + HOURS /**/ = {"ώρα", "ώρες"}, + DAYS /**/ = {"ημέρα", "ημέρες"}, + WEEKS /**/ = {"εβδομάδα", "εβδομάδες"}, + MONTHS /**/ = {"μήνα", "μήνες"}, + YEARS /**/ = {"χρόνια", "χρόνο"}; + + private static final el INSTANCE = new el(); + + public static el getInstance() { + return INSTANCE; + } + + private el() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en.java new file mode 100644 index 000000000..817825df5 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class en extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"second", "seconds"}, + MINUTES /**/ = {"minute", "minutes"}, + HOURS /**/ = {"hour", "hours"}, + DAYS /**/ = {"day", "days"}, + WEEKS /**/ = {"week", "weeks"}, + MONTHS /**/ = {"month", "months"}, + YEARS /**/ = {"year", "years"}; + + private static final en INSTANCE = new en(); + + public static en getInstance() { + return INSTANCE; + } + + private en() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en_GB.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en_GB.java new file mode 100644 index 000000000..d8ce88782 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/en_GB.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class en_GB extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"second", "seconds"}, + MINUTES /**/ = {"minute", "minutes"}, + HOURS /**/ = {"hour", "hours"}, + DAYS /**/ = {"day", "days"}, + WEEKS /**/ = {"week", "weeks"}, + MONTHS /**/ = {"month", "months"}, + YEARS /**/ = {"year", "years"}; + + private static final en_GB INSTANCE = new en_GB(); + + public static en_GB getInstance() { + return INSTANCE; + } + + private en_GB() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es.java new file mode 100644 index 000000000..e41059329 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class es extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"día", "días"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"mes", "meses"}, + YEARS /**/ = {"año", "años"}; + + private static final es INSTANCE = new es(); + + public static es getInstance() { + return INSTANCE; + } + + private es() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_419.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_419.java new file mode 100644 index 000000000..33c7103e6 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_419.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class es_419 extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"día", "días"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"mes", "meses"}, + YEARS /**/ = {"año", "años"}; + + private static final es_419 INSTANCE = new es_419(); + + public static es_419 getInstance() { + return INSTANCE; + } + + private es_419() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_US.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_US.java new file mode 100644 index 000000000..beef678a6 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/es_US.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class es_US extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"día", "días"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"mes", "meses"}, + YEARS /**/ = {"año", "años"}; + + private static final es_US INSTANCE = new es_US(); + + public static es_US getInstance() { + return INSTANCE; + } + + private es_US() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/et.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/et.java new file mode 100644 index 000000000..b53d34b1b --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/et.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class et extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekund", "sekundit"}, + MINUTES /**/ = {"minut", "minutit"}, + HOURS /**/ = {"tund", "tundi"}, + DAYS /**/ = {"päev", "päeva"}, + WEEKS /**/ = {"nädal", "nädalat"}, + MONTHS /**/ = {"kuu", "kuud"}, + YEARS /**/ = {"aasta", "aastat"}; + + private static final et INSTANCE = new et(); + + public static et getInstance() { + return INSTANCE; + } + + private et() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/eu.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/eu.java new file mode 100644 index 000000000..77fd259f6 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/eu.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class eu extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo"}, + MINUTES /**/ = {"minutu"}, + HOURS /**/ = {"ordu", "ordubete"}, + DAYS /**/ = {"egun"}, + WEEKS /**/ = {"aste", "astebete"}, + MONTHS /**/ = {"hilabete"}, + YEARS /**/ = {"urte", "urtebete"}; + + private static final eu INSTANCE = new eu(); + + public static eu getInstance() { + return INSTANCE; + } + + private eu() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fa.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fa.java new file mode 100644 index 000000000..1fe205dde --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fa.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class fa extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"ثانیه"}, + MINUTES /**/ = {"دقیقه"}, + HOURS /**/ = {"ساعت"}, + DAYS /**/ = {"روز"}, + WEEKS /**/ = {"هفته"}, + MONTHS /**/ = {"ماه"}, + YEARS /**/ = {"سال"}; + + private static final fa INSTANCE = new fa(); + + public static fa getInstance() { + return INSTANCE; + } + + private fa() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fi.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fi.java new file mode 100644 index 000000000..6893ef9f9 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fi.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class fi extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekunti", "sekuntia"}, + MINUTES /**/ = {"minuutti", "minuuttia"}, + HOURS /**/ = {"tunti", "tuntia"}, + DAYS /**/ = {"päivä", "päivää"}, + WEEKS /**/ = {"viikko", "viikkoa"}, + MONTHS /**/ = {"kuukausi", "kuukautta"}, + YEARS /**/ = {"vuosi", "vuotta"}; + + private static final fi INSTANCE = new fi(); + + public static fi getInstance() { + return INSTANCE; + } + + private fi() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fil.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fil.java new file mode 100644 index 000000000..3c00686de --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fil.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class fil extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo"}, + MINUTES /**/ = {"minuto"}, + HOURS /**/ = {"oras"}, + DAYS /**/ = {"araw"}, + WEEKS /**/ = {"linggo"}, + MONTHS /**/ = {"buwan"}, + YEARS /**/ = {"taon"}; + + private static final fil INSTANCE = new fil(); + + public static fil getInstance() { + return INSTANCE; + } + + private fil() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr.java new file mode 100644 index 000000000..34f9c02fe --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class fr extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"seconde", "secondes"}, + MINUTES /**/ = {"minute", "minutes"}, + HOURS /**/ = {"heure", "heures"}, + DAYS /**/ = {"jour", "jours"}, + WEEKS /**/ = {"semaine", "semaines"}, + MONTHS /**/ = {"mois"}, + YEARS /**/ = {"an", "ans"}; + + private static final fr INSTANCE = new fr(); + + public static fr getInstance() { + return INSTANCE; + } + + private fr() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr_CA.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr_CA.java new file mode 100644 index 000000000..8f981d31d --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/fr_CA.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class fr_CA extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"seconde", "secondes"}, + MINUTES /**/ = {"minute", "minutes"}, + HOURS /**/ = {"heures", "heure"}, + DAYS /**/ = {"jour", "jours"}, + WEEKS /**/ = {"semaine", "semaines"}, + MONTHS /**/ = {"mois"}, + YEARS /**/ = {"an", "ans"}; + + private static final fr_CA INSTANCE = new fr_CA(); + + public static fr_CA getInstance() { + return INSTANCE; + } + + private fr_CA() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gl.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gl.java new file mode 100644 index 000000000..3ca842f4e --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gl.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class gl extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"día", "días"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"mes", "meses"}, + YEARS /**/ = {"ano", "anos"}; + + private static final gl INSTANCE = new gl(); + + public static gl getInstance() { + return INSTANCE; + } + + private gl() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gu.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gu.java new file mode 100644 index 000000000..cd5749176 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/gu.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class gu extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"સેકંડ"}, + MINUTES /**/ = {"મિનિટ"}, + HOURS /**/ = {"કલાક"}, + DAYS /**/ = {"દિવસ"}, + WEEKS /**/ = {"અઠવાડિયા"}, + MONTHS /**/ = {"મહિના"}, + YEARS /**/ = {"વર્ષ"}; + + private static final gu INSTANCE = new gu(); + + public static gu getInstance() { + return INSTANCE; + } + + private gu() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hi.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hi.java new file mode 100644 index 000000000..bad3c481a --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hi.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class hi extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"सेकंड"}, + MINUTES /**/ = {"मिनट"}, + HOURS /**/ = {"घंटा", "घंटे"}, + DAYS /**/ = {"दिन"}, + WEEKS /**/ = {"सप्ताह", "हफ़्ते"}, + MONTHS /**/ = {"महीना", "महीने"}, + YEARS /**/ = {"वर्ष"}; + + private static final hi INSTANCE = new hi(); + + public static hi getInstance() { + return INSTANCE; + } + + private hi() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hr.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hr.java new file mode 100644 index 000000000..8d5919853 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hr.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class hr extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekunde", "sekundi", "sekundu"}, + MINUTES /**/ = {"minuta", "minute", "minutu"}, + HOURS /**/ = {"sat", "sata", "sati"}, + DAYS /**/ = {"dan", "dana"}, + WEEKS /**/ = {"tjedan", "tjedna"}, + MONTHS /**/ = {"mjesec", "mjeseca", "mjeseci"}, + YEARS /**/ = {"godina", "godine", "godinu"}; + + private static final hr INSTANCE = new hr(); + + public static hr getInstance() { + return INSTANCE; + } + + private hr() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hu.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hu.java new file mode 100644 index 000000000..d869966cf --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hu.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class hu extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"másodperce"}, + MINUTES /**/ = {"perce"}, + HOURS /**/ = {"órája"}, + DAYS /**/ = {"napja"}, + WEEKS /**/ = {"hete"}, + MONTHS /**/ = {"hónapja"}, + YEARS /**/ = {"éve"}; + + private static final hu INSTANCE = new hu(); + + public static hu getInstance() { + return INSTANCE; + } + + private hu() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hy.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hy.java new file mode 100644 index 000000000..9a0fbb8a0 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/hy.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class hy extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"վայրկյան"}, + MINUTES /**/ = {"րոպե"}, + HOURS /**/ = {"ժամ"}, + DAYS /**/ = {"օր"}, + WEEKS /**/ = {"շաբաթ"}, + MONTHS /**/ = {"ամիս"}, + YEARS /**/ = {"տարի"}; + + private static final hy INSTANCE = new hy(); + + public static hy getInstance() { + return INSTANCE; + } + + private hy() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/id.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/id.java new file mode 100644 index 000000000..f4c32c735 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/id.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class id extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"detik"}, + MINUTES /**/ = {"menit"}, + HOURS /**/ = {"jam"}, + DAYS /**/ = {"hari"}, + WEEKS /**/ = {"minggu"}, + MONTHS /**/ = {"bulan"}, + YEARS /**/ = {"tahun"}; + + private static final id INSTANCE = new id(); + + public static id getInstance() { + return INSTANCE; + } + + private id() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/is.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/is.java new file mode 100644 index 000000000..3c4065fd0 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/is.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class is extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekúndu", "sekúndum", "second", "seconds"}, + MINUTES /**/ = {"mínútu", "mínútum", "minute", "minutes"}, + HOURS /**/ = {"klukkustund", "klukkustundum", "hour", "hours"}, + DAYS /**/ = {"degi", "dögum", "day", "days"}, + WEEKS /**/ = {"viku", "vikum", "week", "weeks"}, + MONTHS /**/ = {"mánuði", "mánuðum"}, + YEARS /**/ = {"ári", "árum"}; + + private static final is INSTANCE = new is(); + + public static is getInstance() { + return INSTANCE; + } + + private is() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/it.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/it.java new file mode 100644 index 000000000..78e8e0eb8 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/it.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class it extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"secondi", "secondo"}, + MINUTES /**/ = {"minuti", "minuto"}, + HOURS /**/ = {"ora", "ore"}, + DAYS /**/ = {"giorni", "giorno"}, + WEEKS /**/ = {"settimana", "settimane"}, + MONTHS /**/ = {"mese", "mesi"}, + YEARS /**/ = {"anni", "anno"}; + + private static final it INSTANCE = new it(); + + public static it getInstance() { + return INSTANCE; + } + + private it() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/iw.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/iw.java new file mode 100644 index 000000000..a04bf74f3 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/iw.java @@ -0,0 +1,35 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; +import org.schabi.newpipe.extractor.timeago.TimeAgoUnit; + +public class iw extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"שניות", "שנייה"}, + MINUTES /**/ = {"דקה", "דקות"}, + HOURS /**/ = {"שעה", "שעות"}, + DAYS /**/ = {"יום", "ימים"}, + WEEKS /**/ = {"שבוע", "שבועות"}, + MONTHS /**/ = {"חודש", "חודשים"}, + YEARS /**/ = {"שנה", "שנים"}; + + private static final iw INSTANCE = new iw(); + + public static iw getInstance() { + return INSTANCE; + } + + private iw() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + putSpecialCase(TimeAgoUnit.HOURS, "שעתיים", 2); + putSpecialCase(TimeAgoUnit.DAYS, "יומיים", 2); + putSpecialCase(TimeAgoUnit.WEEKS, "שבועיים", 2); + putSpecialCase(TimeAgoUnit.MONTHS, "חודשיים", 2); + putSpecialCase(TimeAgoUnit.YEARS, "שנתיים", 2); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ja.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ja.java new file mode 100644 index 000000000..a2b8e4759 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ja.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ja extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"秒前"}, + MINUTES /**/ = {"分前"}, + HOURS /**/ = {"時間前"}, + DAYS /**/ = {"日前"}, + WEEKS /**/ = {"週間前"}, + MONTHS /**/ = {"か月前"}, + YEARS /**/ = {"年前"}; + + private static final ja INSTANCE = new ja(); + + public static ja getInstance() { + return INSTANCE; + } + + private ja() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ka.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ka.java new file mode 100644 index 000000000..fc75d1d27 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ka.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ka extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"წამის"}, + MINUTES /**/ = {"წუთის"}, + HOURS /**/ = {"საათის"}, + DAYS /**/ = {"დღის"}, + WEEKS /**/ = {"კვირის"}, + MONTHS /**/ = {"თვის"}, + YEARS /**/ = {"წლის"}; + + private static final ka INSTANCE = new ka(); + + public static ka getInstance() { + return INSTANCE; + } + + private ka() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kk.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kk.java new file mode 100644 index 000000000..2605c0ae1 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kk.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class kk extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунд"}, + MINUTES /**/ = {"минут"}, + HOURS /**/ = {"сағат"}, + DAYS /**/ = {"күн"}, + WEEKS /**/ = {"апта"}, + MONTHS /**/ = {"ай"}, + YEARS /**/ = {"жыл"}; + + private static final kk INSTANCE = new kk(); + + public static kk getInstance() { + return INSTANCE; + } + + private kk() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/km.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/km.java new file mode 100644 index 000000000..5d325a5f6 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/km.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class km extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"វិនាទី​មុន", "១វិនាទីមុន"}, + MINUTES /**/ = {"នាទីមុន", "១នាទីមុន"}, + HOURS /**/ = {"ម៉ោង​មុន", "១ម៉ោង​មុន"}, + DAYS /**/ = {"ថ្ងៃមុន", "១ថ្ងៃ​មុន"}, + WEEKS /**/ = {"ស​ប្តា​ហ៍​មុន", "១ស​ប្តា​ហ៍​មុន"}, + MONTHS /**/ = {"ខែមុន", "១ខែមុន"}, + YEARS /**/ = {"ឆ្នាំ​មុន", "១ឆ្នាំមុន"}; + + private static final km INSTANCE = new km(); + + public static km getInstance() { + return INSTANCE; + } + + private km() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kn.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kn.java new file mode 100644 index 000000000..c0b832bbc --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/kn.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class kn extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"ಸೆಕೆಂಡುಗಳ", "ಸೆಕೆಂಡ್"}, + MINUTES /**/ = {"ನಿಮಿಷಗಳ", "ನಿಮಿಷದ"}, + HOURS /**/ = {"ಗಂಟೆಗಳ", "ಗಂಟೆಯ"}, + DAYS /**/ = {"ದಿನಗಳ", "ದಿನದ"}, + WEEKS /**/ = {"ವಾರಗಳ", "ವಾರದ"}, + MONTHS /**/ = {"ತಿಂಗಳ", "ತಿಂಗಳುಗಳ"}, + YEARS /**/ = {"ವರ್ಷಗಳ", "ವರ್ಷದ"}; + + private static final kn INSTANCE = new kn(); + + public static kn getInstance() { + return INSTANCE; + } + + private kn() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ko.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ko.java new file mode 100644 index 000000000..6665830ce --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ko.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ko extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"초"}, + MINUTES /**/ = {"분"}, + HOURS /**/ = {"시간"}, + DAYS /**/ = {"일"}, + WEEKS /**/ = {"주"}, + MONTHS /**/ = {"개월"}, + YEARS /**/ = {"년"}; + + private static final ko INSTANCE = new ko(); + + public static ko getInstance() { + return INSTANCE; + } + + private ko() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ky.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ky.java new file mode 100644 index 000000000..cb5c6f207 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ky.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ky extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунд"}, + MINUTES /**/ = {"мүнөт"}, + HOURS /**/ = {"саат"}, + DAYS /**/ = {"күн"}, + WEEKS /**/ = {"апта"}, + MONTHS /**/ = {"ай"}, + YEARS /**/ = {"жыл"}; + + private static final ky INSTANCE = new ky(); + + public static ky getInstance() { + return INSTANCE; + } + + private ky() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lo.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lo.java new file mode 100644 index 000000000..acf66136d --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lo.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class lo extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"ວິນາທີກ່ອນນີ້"}, + MINUTES /**/ = {"ນາທີກ່ອນນີ້", "ນາ​ທີ​ກ່ອນ​ນີ້"}, + HOURS /**/ = {"ຊົ່ວ​ໂມງ​ກ່ອນ​ນີ້"}, + DAYS /**/ = {"ມື້ກ່ອນນີ້"}, + WEEKS /**/ = {"ອາ​ທິດ​ກ່ອນ​ນີ້"}, + MONTHS /**/ = {"ເດືອນ​ກ່ອນ​ນີ້"}, + YEARS /**/ = {"ປີ​ກ່ອນ​ນີ້"}; + + private static final lo INSTANCE = new lo(); + + public static lo getInstance() { + return INSTANCE; + } + + private lo() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lt.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lt.java new file mode 100644 index 000000000..2dfcbae60 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lt.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class lt extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundes", "sekundę", "sekundžių"}, + MINUTES /**/ = {"minutes", "minutę", "minučių"}, + HOURS /**/ = {"valandas", "valandą", "valandų"}, + DAYS /**/ = {"dienas", "dieną"}, + WEEKS /**/ = {"savaites", "savaitę"}, + MONTHS /**/ = {"mėnesius", "mėnesių", "mėnesį"}, + YEARS /**/ = {"metus", "metų"}; + + private static final lt INSTANCE = new lt(); + + public static lt getInstance() { + return INSTANCE; + } + + private lt() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lv.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lv.java new file mode 100644 index 000000000..46625b30a --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/lv.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class lv extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundes", "sekundēm"}, + MINUTES /**/ = {"minūtes", "minūtēm", "minūtes"}, + HOURS /**/ = {"stundas", "stundām"}, + DAYS /**/ = {"dienas", "dienām"}, + WEEKS /**/ = {"nedēļas", "nedēļām"}, + MONTHS /**/ = {"mēneša", "mēnešiem"}, + YEARS /**/ = {"gada", "gadiem"}; + + private static final lv INSTANCE = new lv(); + + public static lv getInstance() { + return INSTANCE; + } + + private lv() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mk.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mk.java new file mode 100644 index 000000000..7b8e0d6b9 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mk.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class mk extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунда", "секунди"}, + MINUTES /**/ = {"минута", "минути"}, + HOURS /**/ = {"час", "часа"}, + DAYS /**/ = {"ден", "дена"}, + WEEKS /**/ = {"недела", "недели"}, + MONTHS /**/ = {"месец", "месеци"}, + YEARS /**/ = {"година", "години"}; + + private static final mk INSTANCE = new mk(); + + public static mk getInstance() { + return INSTANCE; + } + + private mk() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ml.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ml.java new file mode 100644 index 000000000..5bf3a90f9 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ml.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ml extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"സെക്കന്റ്", "സെക്കൻഡ്"}, + MINUTES /**/ = {"മിനിറ്റ്"}, + HOURS /**/ = {"മണിക്കൂർ"}, + DAYS /**/ = {"ദിവസം"}, + WEEKS /**/ = {"ആഴ്ച", "ആഴ്‌ച"}, + MONTHS /**/ = {"മാസം"}, + YEARS /**/ = {"വർഷം"}; + + private static final ml INSTANCE = new ml(); + + public static ml getInstance() { + return INSTANCE; + } + + private ml() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mn.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mn.java new file mode 100644 index 000000000..a7222f89b --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mn.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class mn extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секундын"}, + MINUTES /**/ = {"минутын"}, + HOURS /**/ = {"цагийн"}, + DAYS /**/ = {"өдрийн"}, + WEEKS /**/ = {"долоо", "хоногийн"}, + MONTHS /**/ = {"сарын"}, + YEARS /**/ = {"жилийн"}; + + private static final mn INSTANCE = new mn(); + + public static mn getInstance() { + return INSTANCE; + } + + private mn() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mr.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mr.java new file mode 100644 index 000000000..6a50714d7 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/mr.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class mr extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"सेकंदांपूर्वी", "सेकंदापूर्वी"}, + MINUTES /**/ = {"मिनिटांपूर्वी", "मिनिटापूर्वी"}, + HOURS /**/ = {"तासांपूर्वी", "तासापूर्वी"}, + DAYS /**/ = {"दिवसांपूर्वी", "दिवसापूर्वी"}, + WEEKS /**/ = {"आठवड्यांपूर्वी", "आठवड्यापूर्वी"}, + MONTHS /**/ = {"महिन्यांपूर्वी", "महिन्यापूर्वी"}, + YEARS /**/ = {"वर्षांपूर्वी", "वर्षापूर्वी"}; + + private static final mr INSTANCE = new mr(); + + public static mr getInstance() { + return INSTANCE; + } + + private mr() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ms.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ms.java new file mode 100644 index 000000000..115506ad3 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ms.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ms extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"saat"}, + MINUTES /**/ = {"minit"}, + HOURS /**/ = {"jam"}, + DAYS /**/ = {"hari"}, + WEEKS /**/ = {"minggu"}, + MONTHS /**/ = {"bulan"}, + YEARS /**/ = {"tahun"}; + + private static final ms INSTANCE = new ms(); + + public static ms getInstance() { + return INSTANCE; + } + + private ms() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/my.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/my.java new file mode 100644 index 000000000..b7bbf1869 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/my.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class my extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"စက္ကန့်"}, + MINUTES /**/ = {"မိနစ်"}, + HOURS /**/ = {"နာရီ"}, + DAYS /**/ = {"ရက်"}, + WEEKS /**/ = {"ပတ်"}, + MONTHS /**/ = {"လ"}, + YEARS /**/ = {"နှစ်"}; + + private static final my INSTANCE = new my(); + + public static my getInstance() { + return INSTANCE; + } + + private my() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ne.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ne.java new file mode 100644 index 000000000..650d177d5 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ne.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ne extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"सेकेन्ड"}, + MINUTES /**/ = {"मिनेट"}, + HOURS /**/ = {"घन्टा"}, + DAYS /**/ = {"दिन"}, + WEEKS /**/ = {"हप्ता"}, + MONTHS /**/ = {"महिना"}, + YEARS /**/ = {"वर्ष"}; + + private static final ne INSTANCE = new ne(); + + public static ne getInstance() { + return INSTANCE; + } + + private ne() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/nl.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/nl.java new file mode 100644 index 000000000..37f120989 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/nl.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class nl extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"seconde", "seconden"}, + MINUTES /**/ = {"minuten", "minuut"}, + HOURS /**/ = {"uur"}, + DAYS /**/ = {"dag", "dagen"}, + WEEKS /**/ = {"week", "weken"}, + MONTHS /**/ = {"maand", "maanden"}, + YEARS /**/ = {"jaar"}; + + private static final nl INSTANCE = new nl(); + + public static nl getInstance() { + return INSTANCE; + } + + private nl() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/no.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/no.java new file mode 100644 index 000000000..01d4e75ac --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/no.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class no extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekund", "sekunder"}, + MINUTES /**/ = {"minutt", "minutter"}, + HOURS /**/ = {"time", "timer"}, + DAYS /**/ = {"dag", "dager"}, + WEEKS /**/ = {"uke", "uker"}, + MONTHS /**/ = {"md."}, + YEARS /**/ = {"år"}; + + private static final no INSTANCE = new no(); + + public static no getInstance() { + return INSTANCE; + } + + private no() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pa.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pa.java new file mode 100644 index 000000000..4c5ad142c --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pa.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class pa extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"ਸਕਿੰਟ"}, + MINUTES /**/ = {"ਮਿੰਟ"}, + HOURS /**/ = {"ਘੰਟਾ", "ਘੰਟੇ"}, + DAYS /**/ = {"ਦਿਨ"}, + WEEKS /**/ = {"ਹਫ਼ਤਾ", "ਹਫ਼ਤੇ"}, + MONTHS /**/ = {"ਮਹੀਨਾ", "ਮਹੀਨੇ"}, + YEARS /**/ = {"ਸਾਲ"}; + + private static final pa INSTANCE = new pa(); + + public static pa getInstance() { + return INSTANCE; + } + + private pa() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pl.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pl.java new file mode 100644 index 000000000..9e0eddb74 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pl.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class pl extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekund", "sekundy", "sekundę"}, + MINUTES /**/ = {"minut", "minuty", "minutę"}, + HOURS /**/ = {"godzin", "godziny", "godzinę"}, + DAYS /**/ = {"dni", "dzień"}, + WEEKS /**/ = {"tydzień", "tygodnie"}, + MONTHS /**/ = {"miesiąc", "miesiące", "miesięcy"}, + YEARS /**/ = {"lat", "lata", "rok"}; + + private static final pl INSTANCE = new pl(); + + public static pl getInstance() { + return INSTANCE; + } + + private pl() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt.java new file mode 100644 index 000000000..c6c076e03 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class pt extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"dia", "dias"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"meses", "mês"}, + YEARS /**/ = {"ano", "anos"}; + + private static final pt INSTANCE = new pt(); + + public static pt getInstance() { + return INSTANCE; + } + + private pt() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt_PT.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt_PT.java new file mode 100644 index 000000000..35dd7e08d --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/pt_PT.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class pt_PT extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"segundo", "segundos"}, + MINUTES /**/ = {"minuto", "minutos"}, + HOURS /**/ = {"hora", "horas"}, + DAYS /**/ = {"dia", "dias"}, + WEEKS /**/ = {"semana", "semanas"}, + MONTHS /**/ = {"meses", "mês"}, + YEARS /**/ = {"ano", "anos"}; + + private static final pt_PT INSTANCE = new pt_PT(); + + public static pt_PT getInstance() { + return INSTANCE; + } + + private pt_PT() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ro.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ro.java new file mode 100644 index 000000000..bbd386019 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ro.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ro extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"secunde", "secundă"}, + MINUTES /**/ = {"minut", "minute"}, + HOURS /**/ = {"ore", "oră"}, + DAYS /**/ = {"zi", "zile"}, + WEEKS /**/ = {"săptămâni", "săptămână"}, + MONTHS /**/ = {"luni", "lună"}, + YEARS /**/ = {"an", "ani"}; + + private static final ro INSTANCE = new ro(); + + public static ro getInstance() { + return INSTANCE; + } + + private ro() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ru.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ru.java new file mode 100644 index 000000000..947468e6b --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ru.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ru extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунд", "секунду", "секунды", "только что"}, + MINUTES /**/ = {"минут", "минуту", "минуты"}, + HOURS /**/ = {"час", "часа", "часов"}, + DAYS /**/ = {"день", "дней", "дня"}, + WEEKS /**/ = {"Неделю", "недели"}, + MONTHS /**/ = {"месяц", "месяца", "месяцев"}, + YEARS /**/ = {"Год", "года", "лет"}; + + private static final ru INSTANCE = new ru(); + + public static ru getInstance() { + return INSTANCE; + } + + private ru() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/si.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/si.java new file mode 100644 index 000000000..97d27d758 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/si.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class si extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"තත්පර"}, + MINUTES /**/ = {"මිනිත්තු"}, + HOURS /**/ = {"පැය"}, + DAYS /**/ = {"දින"}, + WEEKS /**/ = {"සති"}, + MONTHS /**/ = {"මාස"}, + YEARS /**/ = {"වසර"}; + + private static final si INSTANCE = new si(); + + public static si getInstance() { + return INSTANCE; + } + + private si() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sk.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sk.java new file mode 100644 index 000000000..728cb8547 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sk.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sk extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundami", "sekundou"}, + MINUTES /**/ = {"minútami", "minútou"}, + HOURS /**/ = {"hodinami", "hodinou"}, + DAYS /**/ = {"dňami", "dňom"}, + WEEKS /**/ = {"týždňami", "týždňom"}, + MONTHS /**/ = {"mesiacmi", "mesiacom"}, + YEARS /**/ = {"rokmi", "rokom"}; + + private static final sk INSTANCE = new sk(); + + public static sk getInstance() { + return INSTANCE; + } + + private sk() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sl.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sl.java new file mode 100644 index 000000000..3cf848d12 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sl.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sl extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekundama", "sekundami", "sekundo"}, + MINUTES /**/ = {"minutama", "minutami", "minuto"}, + HOURS /**/ = {"urama", "urami", "uro"}, + DAYS /**/ = {"dnem", "dnevi", "dnevoma"}, + WEEKS /**/ = {"tedni", "tednom", "tednoma"}, + MONTHS /**/ = {"mesecem", "mesecema", "meseci"}, + YEARS /**/ = {"leti", "letom", "letoma"}; + + private static final sl INSTANCE = new sl(); + + public static sl getInstance() { + return INSTANCE; + } + + private sl() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sq.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sq.java new file mode 100644 index 000000000..4f0c19850 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sq.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sq extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekonda", "sekondë"}, + MINUTES /**/ = {"minuta", "minutë"}, + HOURS /**/ = {"orë"}, + DAYS /**/ = {"ditë"}, + WEEKS /**/ = {"javë"}, + MONTHS /**/ = {"muaj"}, + YEARS /**/ = {"vit", "vjet"}; + + private static final sq INSTANCE = new sq(); + + public static sq getInstance() { + return INSTANCE; + } + + private sq() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr.java new file mode 100644 index 000000000..f9af4a865 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sr extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунде", "секунди"}, + MINUTES /**/ = {"минута"}, + HOURS /**/ = {"сат", "сата", "сати"}, + DAYS /**/ = {"Пре 1 дан", "Пре 2 дана", "Пре 3 дана", "Пре 4 дана", "Пре 5 дана", "Пре 6 дана"}, + WEEKS /**/ = {"недеље", "недељу"}, + MONTHS /**/ = {"месец", "месеца", "месеци"}, + YEARS /**/ = {"година", "године", "годину"}; + + private static final sr INSTANCE = new sr(); + + public static sr getInstance() { + return INSTANCE; + } + + private sr() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr_Latn.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr_Latn.java new file mode 100644 index 000000000..e521c53be --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sr_Latn.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sr_Latn extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekunde", "sekundi"}, + MINUTES /**/ = {"minuta"}, + HOURS /**/ = {"sat", "sati", "sata"}, + DAYS /**/ = {"Pre 1 dan", "Pre 2 dana", "Pre 3 dana", "Pre 4 dana", "Pre 5 dana", "Pre 6 dana"}, + WEEKS /**/ = {"nedelja", "nedelje", "nedelju"}, + MONTHS /**/ = {"mesec", "meseci", "meseca"}, + YEARS /**/ = {"godine", "godina", "godinu"}; + + private static final sr_Latn INSTANCE = new sr_Latn(); + + public static sr_Latn getInstance() { + return INSTANCE; + } + + private sr_Latn() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sv.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sv.java new file mode 100644 index 000000000..b23bb24f7 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sv.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sv extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekund", "sekunder"}, + MINUTES /**/ = {"minut", "minuter"}, + HOURS /**/ = {"timmar", "timme"}, + DAYS /**/ = {"dag", "dagar"}, + WEEKS /**/ = {"vecka", "veckor"}, + MONTHS /**/ = {"månad", "månader"}, + YEARS /**/ = {"år"}; + + private static final sv INSTANCE = new sv(); + + public static sv getInstance() { + return INSTANCE; + } + + private sv() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sw.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sw.java new file mode 100644 index 000000000..6b439e9c8 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/sw.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class sw extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"sekunde"}, + MINUTES /**/ = {"dakika"}, + HOURS /**/ = {"saa"}, + DAYS /**/ = {"siku"}, + WEEKS /**/ = {"wiki"}, + MONTHS /**/ = {"Mwezi", "miezi"}, + YEARS /**/ = {"Miaka", "Mwaka"}; + + private static final sw INSTANCE = new sw(); + + public static sw getInstance() { + return INSTANCE; + } + + private sw() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ta.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ta.java new file mode 100644 index 000000000..bfd539dad --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ta.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ta extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"வினாடி", "வினாடிகளுக்கு"}, + MINUTES /**/ = {"நிமிடங்கள்", "நிமிடம்"}, + HOURS /**/ = {"மணிநேரத்திற்கு"}, + DAYS /**/ = {"நாட்களுக்கு", "நாளுக்கு"}, + WEEKS /**/ = {"வாரங்களுக்கு", "வாரம்"}, + MONTHS /**/ = {"மாதங்கள்", "மாதம்"}, + YEARS /**/ = {"ஆண்டு", "ஆண்டுகளுக்கு"}; + + private static final ta INSTANCE = new ta(); + + public static ta getInstance() { + return INSTANCE; + } + + private ta() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/te.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/te.java new file mode 100644 index 000000000..e628c0ed3 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/te.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class te extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"సెకను", "సెకన్ల"}, + MINUTES /**/ = {"నిమిషం", "నిమిషాల"}, + HOURS /**/ = {"గంట", "గంటల"}, + DAYS /**/ = {"రోజు", "రోజుల"}, + WEEKS /**/ = {"వారం", "వారాల"}, + MONTHS /**/ = {"నెల", "నెలల"}, + YEARS /**/ = {"సంవత్సరం", "సంవత్సరాల"}; + + private static final te INSTANCE = new te(); + + public static te getInstance() { + return INSTANCE; + } + + private te() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/th.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/th.java new file mode 100644 index 000000000..aa57d4009 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/th.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class th extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"วินาทีที่ผ่านมา"}, + MINUTES /**/ = {"นาทีที่ผ่านมา"}, + HOURS /**/ = {"ชั่วโมงที่ผ่านมา"}, + DAYS /**/ = {"วันที่ผ่านมา"}, + WEEKS /**/ = {"สัปดาห์ที่ผ่านมา"}, + MONTHS /**/ = {"เดือนที่ผ่านมา"}, + YEARS /**/ = {"ปีที่ผ่านมา"}; + + private static final th INSTANCE = new th(); + + public static th getInstance() { + return INSTANCE; + } + + private th() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/tr.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/tr.java new file mode 100644 index 000000000..49d5e5b54 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/tr.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class tr extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"saniye"}, + MINUTES /**/ = {"dakika"}, + HOURS /**/ = {"saat"}, + DAYS /**/ = {"gün"}, + WEEKS /**/ = {"hafta"}, + MONTHS /**/ = {"ay"}, + YEARS /**/ = {"yıl"}; + + private static final tr INSTANCE = new tr(); + + public static tr getInstance() { + return INSTANCE; + } + + private tr() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uk.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uk.java new file mode 100644 index 000000000..93bea8fc9 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uk.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class uk extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"секунд", "секунди", "секунду"}, + MINUTES /**/ = {"хвилин", "хвилини", "хвилину"}, + HOURS /**/ = {"годин", "години", "годину"}, + DAYS /**/ = {"день", "дні", "днів"}, + WEEKS /**/ = {"тиждень", "тижні"}, + MONTHS /**/ = {"місяць", "місяці", "місяців"}, + YEARS /**/ = {"роки", "років", "рік"}; + + private static final uk INSTANCE = new uk(); + + public static uk getInstance() { + return INSTANCE; + } + + private uk() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ur.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ur.java new file mode 100644 index 000000000..56641ded0 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/ur.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class ur extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"سیکنڈ", "سیکنڈز"}, + MINUTES /**/ = {"منٹ", "منٹس"}, + HOURS /**/ = {"گھنٹہ", "گھنٹے"}, + DAYS /**/ = {"دن"}, + WEEKS /**/ = {"ہفتہ", "ہفتے"}, + MONTHS /**/ = {"ماہ"}, + YEARS /**/ = {"سال"}; + + private static final ur INSTANCE = new ur(); + + public static ur getInstance() { + return INSTANCE; + } + + private ur() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uz.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uz.java new file mode 100644 index 000000000..422cd7eba --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/uz.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class uz extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"soniya"}, + MINUTES /**/ = {"daqiqa"}, + HOURS /**/ = {"soat"}, + DAYS /**/ = {"kun"}, + WEEKS /**/ = {"hafta"}, + MONTHS /**/ = {"oy"}, + YEARS /**/ = {"yil"}; + + private static final uz INSTANCE = new uz(); + + public static uz getInstance() { + return INSTANCE; + } + + private uz() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/vi.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/vi.java new file mode 100644 index 000000000..96932f813 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/vi.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class vi extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"giây"}, + MINUTES /**/ = {"phút"}, + HOURS /**/ = {"giờ", "tiếng"}, + DAYS /**/ = {"ngày"}, + WEEKS /**/ = {"tuần"}, + MONTHS /**/ = {"tháng"}, + YEARS /**/ = {"năm"}; + + private static final vi INSTANCE = new vi(); + + public static vi getInstance() { + return INSTANCE; + } + + private vi() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_CN.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_CN.java new file mode 100644 index 000000000..df5513077 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_CN.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class zh_CN extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"秒前"}, + MINUTES /**/ = {"分钟前"}, + HOURS /**/ = {"小时前"}, + DAYS /**/ = {"天前"}, + WEEKS /**/ = {"周前"}, + MONTHS /**/ = {"个月前"}, + YEARS /**/ = {"年前"}; + + private static final zh_CN INSTANCE = new zh_CN(); + + public static zh_CN getInstance() { + return INSTANCE; + } + + private zh_CN() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_HK.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_HK.java new file mode 100644 index 000000000..08bc73eb9 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_HK.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class zh_HK extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"秒前"}, + MINUTES /**/ = {"分鐘前"}, + HOURS /**/ = {"小時前"}, + DAYS /**/ = {"天前"}, + WEEKS /**/ = {"週前"}, + MONTHS /**/ = {"個月前"}, + YEARS /**/ = {"年前"}; + + private static final zh_HK INSTANCE = new zh_HK(); + + public static zh_HK getInstance() { + return INSTANCE; + } + + private zh_HK() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_TW.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_TW.java new file mode 100644 index 000000000..8d3b07bba --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zh_TW.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class zh_TW extends PatternsHolder { + private static final String WORD_SEPARATOR = ""; + private static final String[] + SECONDS /**/ = {"秒前"}, + MINUTES /**/ = {"分鐘前"}, + HOURS /**/ = {"小時前"}, + DAYS /**/ = {"天前"}, + WEEKS /**/ = {"週前"}, + MONTHS /**/ = {"個月前"}, + YEARS /**/ = {"年前"}; + + private static final zh_TW INSTANCE = new zh_TW(); + + public static zh_TW getInstance() { + return INSTANCE; + } + + private zh_TW() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zu.java b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zu.java new file mode 100644 index 000000000..8599e0027 --- /dev/null +++ b/timeago-parser/src/main/java/org/schabi/newpipe/extractor/timeago/patterns/zu.java @@ -0,0 +1,29 @@ +/**/// DO NOT MODIFY THIS FILE MANUALLY +/**/// This class was automatically generated by "GeneratePatternClasses.java", +/**/// modify the "unique_patterns.json" and re-generate instead. + +package org.schabi.newpipe.extractor.timeago.patterns; + +import org.schabi.newpipe.extractor.timeago.PatternsHolder; + +public class zu extends PatternsHolder { + private static final String WORD_SEPARATOR = " "; + private static final String[] + SECONDS /**/ = {"amasekhondi", "isekhondi"}, + MINUTES /**/ = {"amaminithi", "iminithi"}, + HOURS /**/ = {"amahora", "ihora"}, + DAYS /**/ = {"izinsuku", "usuku"}, + WEEKS /**/ = {"amaviki", "iviki"}, + MONTHS /**/ = {"inyanga", "izinyanga"}, + YEARS /**/ = {"iminyaka", "unyaka"}; + + private static final zu INSTANCE = new zu(); + + public static zu getInstance() { + return INSTANCE; + } + + private zu() { + super(WORD_SEPARATOR, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS); + } +} \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_af.properties b/timeago-parser/src/main/resources/i18n/time_units_af.properties deleted file mode 100644 index 1cce699fc..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_af.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - sekonde»»\ - sekondes - -minutes=\ - minute»»\ - minuut - -hours=\ - ure»»\ - uur - -days=\ - dae»»\ - dag - -weeks=\ - week»»\ - weke - -months=\ - maand»»\ - maande - -years=\ - jaar \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_am.properties b/timeago-parser/src/main/resources/i18n/time_units_am.properties deleted file mode 100644 index f3b5bd4ac..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_am.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - ሰኮንዶች»»\ - ሴኮንድ - -minutes=\ - ደቂቃ»»\ - ደቂቃዎች - -hours=\ - ሰዓት»»\ - ሰዓቶች - -days=\ - ቀን»»\ - ቀኖች - -weeks=\ - ሳምንታት»»\ - ሳምንት - -months=\ - ወራት»»\ - ወር - -years=\ - ዓመታት»»\ - ዓመት \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ar.properties b/timeago-parser/src/main/resources/i18n/time_units_ar.properties deleted file mode 100644 index 26bdc9b35..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ar.properties +++ /dev/null @@ -1,35 +0,0 @@ -seconds=\ - ثانية»»\ - ثانيتين»»\ - ثوانٍ - -minutes=\ - دقائق»»\ - دقيقة»»\ - دقيقتين - -hours=\ - ساعات»»\ - ساعة»»\ - ساعتين - -days=\ - أيام»»\ - يوم»»\ - يومين - -weeks=\ - أسابيع»»\ - أسبوع»»\ - أسبوعين - -months=\ - أشهر»»\ - شهر»»\ - شهرين»»\ - شهرًا - -years=\ - سنة»»\ - سنتين»»\ - سنوات \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_az.properties b/timeago-parser/src/main/resources/i18n/time_units_az.properties deleted file mode 100644 index aa7bca38d..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_az.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - saniyə - -minutes=\ - dəqiqə - -hours=\ - saat - -days=\ - gün - -weeks=\ - həftə - -months=\ - ay - -years=\ - il \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_be.properties b/timeago-parser/src/main/resources/i18n/time_units_be.properties deleted file mode 100644 index dbc33920a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_be.properties +++ /dev/null @@ -1,28 +0,0 @@ -seconds=\ - секунд»»\ - секунду»»\ - секунды - -minutes=\ - хвіліну»»\ - хвіліны - -hours=\ - гадзіну»»\ - гадзіны - -days=\ - дзень»»\ - дня - -weeks=\ - тыдзень»»\ - тыдня - -months=\ - месяц»»\ - месяца - -years=\ - год»»\ - года \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_bg.properties b/timeago-parser/src/main/resources/i18n/time_units_bg.properties deleted file mode 100644 index c0c974c96..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_bg.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - секунда»»\ - секунди - -minutes=\ - минута»»\ - минути - -hours=\ - час»»\ - часа - -days=\ - ден»»\ - дни - -weeks=\ - седмица»»\ - седмици - -months=\ - месец»»\ - месеца - -years=\ - година»»\ - години \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_bn.properties b/timeago-parser/src/main/resources/i18n/time_units_bn.properties deleted file mode 100644 index f14bcc133..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_bn.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - সেকেন্ড - -minutes=\ - মিনিট - -hours=\ - ঘণ্টা - -days=\ - দিন - -weeks=\ - সপ্তাহ - -months=\ - মাস - -years=\ - বছর \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_bs.properties b/timeago-parser/src/main/resources/i18n/time_units_bs.properties deleted file mode 100644 index 11a8dd725..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_bs.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekundi»»\ - sekundu - -minutes=\ - minuta»»\ - minutu - -hours=\ - h»»\ - sat - -days=\ - dan»»\ - dana - -weeks=\ - sedm. - -months=\ - mj.»»\ - mjesec - -years=\ - godine»»\ - godina»»\ - godinu \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ca.properties b/timeago-parser/src/main/resources/i18n/time_units_ca.properties deleted file mode 100644 index a7adcd437..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ca.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segon»»\ - segons - -minutes=\ - minut»»\ - minuts - -hours=\ - hora»»\ - hores - -days=\ - dia»»\ - dies - -weeks=\ - setmana»»\ - setmanes - -months=\ - mes»»\ - mesos - -years=\ - any»»\ - anys \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_cs.properties b/timeago-parser/src/main/resources/i18n/time_units_cs.properties deleted file mode 100644 index baccfa018..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_cs.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekundami»»\ - sekundou - -minutes=\ - minutami»»\ - minutou - -hours=\ - hodinami»»\ - hodinou - -days=\ - dny»»\ - včera - -weeks=\ - týdnem»»\ - týdny - -months=\ - měsícem»»\ - měsíci - -years=\ - rokem»»\ - roky \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_da.properties b/timeago-parser/src/main/resources/i18n/time_units_da.properties deleted file mode 100644 index a907e7258..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_da.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - sekund»»\ - sekunder - -minutes=\ - minut»»\ - minutter - -hours=\ - time»»\ - timer - -days=\ - dag»»\ - dage - -weeks=\ - uge»»\ - uger - -months=\ - måned»»\ - måneder - -years=\ - år \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_de.properties b/timeago-parser/src/main/resources/i18n/time_units_de.properties deleted file mode 100644 index 94a2bcec6..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_de.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - Sekunde»»\ - Sekunden - -minutes=\ - Minute»»\ - Minuten - -hours=\ - Stunde»»\ - Stunden - -days=\ - Tag»»\ - Tagen - -weeks=\ - Woche»»\ - Wochen - -months=\ - Monat»»\ - Monaten - -years=\ - Jahr»»\ - Jahren \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_el.properties b/timeago-parser/src/main/resources/i18n/time_units_el.properties deleted file mode 100644 index ced7c8448..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_el.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - δευτερόλεπτα»»\ - δευτερόλεπτο - -minutes=\ - λεπτά»»\ - λεπτό - -hours=\ - ώρα»»\ - ώρες - -days=\ - ημέρα»»\ - ημέρες - -weeks=\ - εβδομάδα»»\ - εβδομάδες - -months=\ - μήνα»»\ - μήνες - -years=\ - χρόνια»»\ - χρόνο \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_en.properties b/timeago-parser/src/main/resources/i18n/time_units_en.properties deleted file mode 100644 index 55746f4b7..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_en.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - second»»\ - seconds - -minutes=\ - minute»»\ - minutes - -hours=\ - hour»»\ - hours - -days=\ - day»»\ - days - -weeks=\ - week»»\ - weeks - -months=\ - month»»\ - months - -years=\ - year»»\ - years \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_en_GB.properties b/timeago-parser/src/main/resources/i18n/time_units_en_GB.properties deleted file mode 100644 index 55746f4b7..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_en_GB.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - second»»\ - seconds - -minutes=\ - minute»»\ - minutes - -hours=\ - hour»»\ - hours - -days=\ - day»»\ - days - -weeks=\ - week»»\ - weeks - -months=\ - month»»\ - months - -years=\ - year»»\ - years \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_es.properties b/timeago-parser/src/main/resources/i18n/time_units_es.properties deleted file mode 100644 index 1ac3fcdee..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_es.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - día»»\ - días - -weeks=\ - semana»»\ - semanas - -months=\ - mes»»\ - meses - -years=\ - año»»\ - años \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_es_419.properties b/timeago-parser/src/main/resources/i18n/time_units_es_419.properties deleted file mode 100644 index 1ac3fcdee..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_es_419.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - día»»\ - días - -weeks=\ - semana»»\ - semanas - -months=\ - mes»»\ - meses - -years=\ - año»»\ - años \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_es_US.properties b/timeago-parser/src/main/resources/i18n/time_units_es_US.properties deleted file mode 100644 index 1ac3fcdee..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_es_US.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - día»»\ - días - -weeks=\ - semana»»\ - semanas - -months=\ - mes»»\ - meses - -years=\ - año»»\ - años \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_et.properties b/timeago-parser/src/main/resources/i18n/time_units_et.properties deleted file mode 100644 index 8277a5134..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_et.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekund»»\ - sekundit - -minutes=\ - minut»»\ - minutit - -hours=\ - tund»»\ - tundi - -days=\ - päev»»\ - päeva - -weeks=\ - nädal»»\ - nädalat - -months=\ - kuu»»\ - kuud - -years=\ - aasta»»\ - aastat \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_eu.properties b/timeago-parser/src/main/resources/i18n/time_units_eu.properties deleted file mode 100644 index b27fbeb77..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_eu.properties +++ /dev/null @@ -1,23 +0,0 @@ -seconds=\ - segundo - -minutes=\ - minutu - -hours=\ - ordu»»\ - ordubete - -days=\ - egun - -weeks=\ - aste»»\ - astebete - -months=\ - hilabete - -years=\ - urte»»\ - urtebete \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_fa.properties b/timeago-parser/src/main/resources/i18n/time_units_fa.properties deleted file mode 100644 index d7901d582..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_fa.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - ثانیه - -minutes=\ - دقیقه - -hours=\ - ساعت - -days=\ - روز - -weeks=\ - هفته - -months=\ - ماه - -years=\ - سال \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_fi.properties b/timeago-parser/src/main/resources/i18n/time_units_fi.properties deleted file mode 100644 index 15f0a89d8..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_fi.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekunti»»\ - sekuntia - -minutes=\ - minuutti»»\ - minuuttia - -hours=\ - tunti»»\ - tuntia - -days=\ - päivä»»\ - päivää - -weeks=\ - viikko»»\ - viikkoa - -months=\ - kuukausi»»\ - kuukautta - -years=\ - vuosi»»\ - vuotta \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_fil.properties b/timeago-parser/src/main/resources/i18n/time_units_fil.properties deleted file mode 100644 index 35f060cda..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_fil.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - segundo - -minutes=\ - minuto - -hours=\ - oras - -days=\ - araw - -weeks=\ - linggo - -months=\ - buwan - -years=\ - taon \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_fr.properties b/timeago-parser/src/main/resources/i18n/time_units_fr.properties deleted file mode 100644 index a8f4a63d5..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_fr.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - seconde»»\ - secondes - -minutes=\ - minute»»\ - minutes - -hours=\ - heure»»\ - heures - -days=\ - jour»»\ - jours - -weeks=\ - semaine»»\ - semaines - -months=\ - mois - -years=\ - an»»\ - ans \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_fr_CA.properties b/timeago-parser/src/main/resources/i18n/time_units_fr_CA.properties deleted file mode 100644 index 376adfabf..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_fr_CA.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - seconde»»\ - secondes - -minutes=\ - minute»»\ - minutes - -hours=\ - heures»»\ - heure - -days=\ - jour»»\ - jours - -weeks=\ - semaine»»\ - semaines - -months=\ - mois - -years=\ - an»»\ - ans \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_gl.properties b/timeago-parser/src/main/resources/i18n/time_units_gl.properties deleted file mode 100644 index f075bd251..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_gl.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - día»»\ - días - -weeks=\ - semana»»\ - semanas - -months=\ - mes»»\ - meses - -years=\ - ano»»\ - anos \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_gu.properties b/timeago-parser/src/main/resources/i18n/time_units_gu.properties deleted file mode 100644 index 4d876649a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_gu.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - સેકંડ - -minutes=\ - મિનિટ - -hours=\ - કલાક - -days=\ - દિવસ - -weeks=\ - અઠવાડિયા - -months=\ - મહિના - -years=\ - વર્ષ \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_hi.properties b/timeago-parser/src/main/resources/i18n/time_units_hi.properties deleted file mode 100644 index 112653213..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_hi.properties +++ /dev/null @@ -1,22 +0,0 @@ -seconds=\ - सेकंड - -minutes=\ - मिनट - -hours=\ - घंटा»»\ - घंटे - -days=\ - दिन - -weeks=\ - सप्ताह - -months=\ - महीना»»\ - महीने - -years=\ - वर्ष \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_hr.properties b/timeago-parser/src/main/resources/i18n/time_units_hr.properties deleted file mode 100644 index c8dfbd269..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_hr.properties +++ /dev/null @@ -1,32 +0,0 @@ -seconds=\ - sekunde»»\ - sekundi»»\ - sekundu - -minutes=\ - minuta»»\ - minute»»\ - minutu - -hours=\ - sat»»\ - sata»»\ - sati - -days=\ - dan»»\ - dana - -weeks=\ - tjedan»»\ - tjedna - -months=\ - mjesec»»\ - mjeseca»»\ - mjeseci - -years=\ - godina»»\ - godine»»\ - godinu \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_hu.properties b/timeago-parser/src/main/resources/i18n/time_units_hu.properties deleted file mode 100644 index bc6a3420b..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_hu.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - másodperce - -minutes=\ - perce - -hours=\ - órája - -days=\ - napja - -weeks=\ - hete - -months=\ - hónapja - -years=\ - éve \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_hy.properties b/timeago-parser/src/main/resources/i18n/time_units_hy.properties deleted file mode 100644 index ba46e2843..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_hy.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - վայրկյան - -minutes=\ - րոպե - -hours=\ - ժամ - -days=\ - օր - -weeks=\ - շաբաթ - -months=\ - ամիս - -years=\ - տարի \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_id.properties b/timeago-parser/src/main/resources/i18n/time_units_id.properties deleted file mode 100644 index 882a1c738..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_id.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - detik - -minutes=\ - menit - -hours=\ - jam - -days=\ - hari - -weeks=\ - minggu - -months=\ - bulan - -years=\ - tahun \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_is.properties b/timeago-parser/src/main/resources/i18n/time_units_is.properties deleted file mode 100644 index 29ea84c8e..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_is.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekúndu»»\ - sekúndum - -minutes=\ - mínútu»»\ - mínútum - -hours=\ - klukkustund»»\ - klukkustundum - -days=\ - degi»»\ - dögum - -weeks=\ - viku»»\ - vikum - -months=\ - mánuði»»\ - mánuðum - -years=\ - ári»»\ - árum \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_it.properties b/timeago-parser/src/main/resources/i18n/time_units_it.properties deleted file mode 100644 index 1826834e5..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_it.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - secondi»»\ - secondo - -minutes=\ - minuti»»\ - minuto - -hours=\ - ora»»\ - ore - -days=\ - giorni»»\ - giorno - -weeks=\ - settimana»»\ - settimane - -months=\ - mese»»\ - mesi - -years=\ - anni»»\ - anno \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_iw.properties b/timeago-parser/src/main/resources/i18n/time_units_iw.properties deleted file mode 100644 index 67fae0227..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_iw.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - שניות»»\ - שנייה - -minutes=\ - דקה»»\ - דקות - -hours=\ - שעה»»\ - שעות - -days=\ - יום»»\ - ימים - -weeks=\ - שבוע»»\ - שבועות - -months=\ - חודש»»\ - חודשים - -years=\ - שנה»»\ - שנים \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ja.properties b/timeago-parser/src/main/resources/i18n/time_units_ja.properties deleted file mode 100644 index 59958075a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ja.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - 秒前 - -minutes=\ - 分前 - -hours=\ - 時間前 - -days=\ - 日前 - -weeks=\ - 週間前 - -months=\ - か月前 - -years=\ - 年前 \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ka.properties b/timeago-parser/src/main/resources/i18n/time_units_ka.properties deleted file mode 100644 index 37cc083e6..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ka.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - წამის - -minutes=\ - წუთის - -hours=\ - საათის - -days=\ - დღის - -weeks=\ - კვირის - -months=\ - თვის - -years=\ - წლის \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_kk.properties b/timeago-parser/src/main/resources/i18n/time_units_kk.properties deleted file mode 100644 index ce089ece6..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_kk.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - секунд - -minutes=\ - минут - -hours=\ - сағат - -days=\ - күн - -weeks=\ - апта - -months=\ - ай - -years=\ - жыл \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_km.properties b/timeago-parser/src/main/resources/i18n/time_units_km.properties deleted file mode 100644 index 5eaf8c002..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_km.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - វិនាទី​មុន»»\ - ១វិនាទីមុន - -minutes=\ - នាទីមុន»»\ - ១នាទីមុន - -hours=\ - ម៉ោង​មុន»»\ - ១ម៉ោង​មុន - -days=\ - ថ្ងៃមុន»»\ - ១ថ្ងៃ​មុន - -weeks=\ - ស​ប្តា​ហ៍​មុន»»\ - ១ស​ប្តា​ហ៍​មុន - -months=\ - ខែមុន»»\ - ១ខែមុន - -years=\ - ឆ្នាំ​មុន»»\ - ១ឆ្នាំមុន \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_kn.properties b/timeago-parser/src/main/resources/i18n/time_units_kn.properties deleted file mode 100644 index ed0b0e11d..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_kn.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - ಸೆಕೆಂಡುಗಳ»»\ - ಸೆಕೆಂಡ್ - -minutes=\ - ನಿಮಿಷಗಳ»»\ - ನಿಮಿಷದ - -hours=\ - ಗಂಟೆಗಳ»»\ - ಗಂಟೆಯ - -days=\ - ದಿನಗಳ»»\ - ದಿನದ - -weeks=\ - ವಾರಗಳ»»\ - ವಾರದ - -months=\ - ತಿಂಗಳ»»\ - ತಿಂಗಳುಗಳ - -years=\ - ವರ್ಷಗಳ»»\ - ವರ್ಷದ \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ko.properties b/timeago-parser/src/main/resources/i18n/time_units_ko.properties deleted file mode 100644 index 1a61b97cc..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ko.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - 초 - -minutes=\ - 분 - -hours=\ - 시간 - -days=\ - 일 - -weeks=\ - 주 - -months=\ - 개월 - -years=\ - 년 \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ky.properties b/timeago-parser/src/main/resources/i18n/time_units_ky.properties deleted file mode 100644 index 98180e1bb..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ky.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - секунд - -minutes=\ - мүнөт - -hours=\ - саат - -days=\ - күн - -weeks=\ - апта - -months=\ - ай - -years=\ - жыл \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_lo.properties b/timeago-parser/src/main/resources/i18n/time_units_lo.properties deleted file mode 100644 index 95792422f..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_lo.properties +++ /dev/null @@ -1,21 +0,0 @@ -seconds=\ - ວິນາທີກ່ອນນີ້ - -minutes=\ - ນາທີກ່ອນນີ້»»\ - ນາ​ທີ​ກ່ອນ​ນີ້ - -hours=\ - ຊົ່ວ​ໂມງ​ກ່ອນ​ນີ້ - -days=\ - ມື້ກ່ອນນີ້ - -weeks=\ - ອາ​ທິດ​ກ່ອນ​ນີ້ - -months=\ - ເດືອນ​ກ່ອນ​ນີ້ - -years=\ - ປີ​ກ່ອນ​ນີ້ \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_lt.properties b/timeago-parser/src/main/resources/i18n/time_units_lt.properties deleted file mode 100644 index e3ff64c29..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_lt.properties +++ /dev/null @@ -1,31 +0,0 @@ -seconds=\ - sekundes»»\ - sekundę»»\ - sekundžių - -minutes=\ - minutes»»\ - minutę»»\ - minučių - -hours=\ - valandas»»\ - valandą»»\ - valandų - -days=\ - dienas»»\ - dieną - -weeks=\ - savaites»»\ - savaitę - -months=\ - mėnesius»»\ - mėnesių»»\ - mėnesį - -years=\ - metus»»\ - metų \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_lv.properties b/timeago-parser/src/main/resources/i18n/time_units_lv.properties deleted file mode 100644 index bf3f3a67e..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_lv.properties +++ /dev/null @@ -1,28 +0,0 @@ -seconds=\ - sekundes»»\ - sekundēm - -minutes=\ - minūtes»»\ - minūtēm»»\ - minūtes - -hours=\ - stundas»»\ - stundām - -days=\ - dienas»»\ - dienām - -weeks=\ - nedēļas»»\ - nedēļām - -months=\ - mēneša»»\ - mēnešiem - -years=\ - gada»»\ - gadiem \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_mk.properties b/timeago-parser/src/main/resources/i18n/time_units_mk.properties deleted file mode 100644 index 2c88fbb89..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_mk.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - секунда»»\ - секунди - -minutes=\ - минута»»\ - минути - -hours=\ - час»»\ - часа - -days=\ - ден»»\ - дена - -weeks=\ - недела»»\ - недели - -months=\ - месец»»\ - месеци - -years=\ - година»»\ - години \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ml.properties b/timeago-parser/src/main/resources/i18n/time_units_ml.properties deleted file mode 100644 index 556e44f3c..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ml.properties +++ /dev/null @@ -1,22 +0,0 @@ -seconds=\ - സെക്കന്റ്»»\ - സെക്കൻഡ് - -minutes=\ - മിനിറ്റ് - -hours=\ - മണിക്കൂർ - -days=\ - ദിവസം - -weeks=\ - ആഴ്ച»»\ - ആഴ്‌ച - -months=\ - മാസം - -years=\ - വർഷം \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_mn.properties b/timeago-parser/src/main/resources/i18n/time_units_mn.properties deleted file mode 100644 index ae1ed95c8..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_mn.properties +++ /dev/null @@ -1,21 +0,0 @@ -seconds=\ - секундын - -minutes=\ - минутын - -hours=\ - цагийн - -days=\ - өдрийн - -weeks=\ - долоо»»\ - хоногийн - -months=\ - сарын - -years=\ - жилийн \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_mr.properties b/timeago-parser/src/main/resources/i18n/time_units_mr.properties deleted file mode 100644 index 9b78d0715..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_mr.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - सेकंदांपूर्वी»»\ - सेकंदापूर्वी - -minutes=\ - मिनिटांपूर्वी»»\ - मिनिटापूर्वी - -hours=\ - तासांपूर्वी»»\ - तासापूर्वी - -days=\ - दिवसांपूर्वी»»\ - दिवसापूर्वी - -weeks=\ - आठवड्यांपूर्वी»»\ - आठवड्यापूर्वी - -months=\ - महिन्यांपूर्वी»»\ - महिन्यापूर्वी - -years=\ - वर्षांपूर्वी»»\ - वर्षापूर्वी \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ms.properties b/timeago-parser/src/main/resources/i18n/time_units_ms.properties deleted file mode 100644 index 234fe3495..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ms.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - saat - -minutes=\ - minit - -hours=\ - jam - -days=\ - hari - -weeks=\ - minggu - -months=\ - bulan - -years=\ - tahun \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_my.properties b/timeago-parser/src/main/resources/i18n/time_units_my.properties deleted file mode 100644 index 5a6e1933a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_my.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - စက္ကန့် - -minutes=\ - မိနစ် - -hours=\ - နာရီ - -days=\ - ရက် - -weeks=\ - ပတ် - -months=\ - လ - -years=\ - နှစ် \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ne.properties b/timeago-parser/src/main/resources/i18n/time_units_ne.properties deleted file mode 100644 index 0ff38ae1b..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ne.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - सेकेन्ड - -minutes=\ - मिनेट - -hours=\ - घन्टा - -days=\ - दिन - -weeks=\ - हप्ता - -months=\ - महिना - -years=\ - वर्ष \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_nl.properties b/timeago-parser/src/main/resources/i18n/time_units_nl.properties deleted file mode 100644 index 852b5abd5..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_nl.properties +++ /dev/null @@ -1,25 +0,0 @@ -seconds=\ - seconde»»\ - seconden - -minutes=\ - minuten»»\ - minuut - -hours=\ - uur - -days=\ - dag»»\ - dagen - -weeks=\ - week»»\ - weken - -months=\ - maand»»\ - maanden - -years=\ - jaar \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_no.properties b/timeago-parser/src/main/resources/i18n/time_units_no.properties deleted file mode 100644 index f71158b95..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_no.properties +++ /dev/null @@ -1,25 +0,0 @@ -seconds=\ - sekund»»\ - sekunder - -minutes=\ - minutt»»\ - minutter - -hours=\ - time»»\ - timer - -days=\ - dag»»\ - dager - -weeks=\ - uke»»\ - uker - -months=\ - md. - -years=\ - år \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_pa.properties b/timeago-parser/src/main/resources/i18n/time_units_pa.properties deleted file mode 100644 index f6df5f0e1..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_pa.properties +++ /dev/null @@ -1,23 +0,0 @@ -seconds=\ - ਸਕਿੰਟ - -minutes=\ - ਮਿੰਟ - -hours=\ - ਘੰਟਾ»»\ - ਘੰਟੇ - -days=\ - ਦਿਨ - -weeks=\ - ਹਫ਼ਤਾ»»\ - ਹਫ਼ਤੇ - -months=\ - ਮਹੀਨਾ»»\ - ਮਹੀਨੇ - -years=\ - ਸਾਲ \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_pl.properties b/timeago-parser/src/main/resources/i18n/time_units_pl.properties deleted file mode 100644 index 8816db395..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_pl.properties +++ /dev/null @@ -1,32 +0,0 @@ -seconds=\ - sekund»»\ - sekundy»»\ - sekundę - -minutes=\ - minut»»\ - minuty»»\ - minutę - -hours=\ - godzin»»\ - godziny»»\ - godzinę - -days=\ - dni»»\ - dzień - -weeks=\ - tydzień»»\ - tygodnie - -months=\ - miesiąc»»\ - miesiące»»\ - miesięcy - -years=\ - lat»»\ - lata»»\ - rok \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_pt.properties b/timeago-parser/src/main/resources/i18n/time_units_pt.properties deleted file mode 100644 index ebfe11bc2..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_pt.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - dia»»\ - dias - -weeks=\ - semana»»\ - semanas - -months=\ - meses»»\ - mês - -years=\ - ano»»\ - anos \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_pt_PT.properties b/timeago-parser/src/main/resources/i18n/time_units_pt_PT.properties deleted file mode 100644 index ebfe11bc2..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_pt_PT.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - segundo»»\ - segundos - -minutes=\ - minuto»»\ - minutos - -hours=\ - hora»»\ - horas - -days=\ - dia»»\ - dias - -weeks=\ - semana»»\ - semanas - -months=\ - meses»»\ - mês - -years=\ - ano»»\ - anos \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ro.properties b/timeago-parser/src/main/resources/i18n/time_units_ro.properties deleted file mode 100644 index e7802bc3d..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ro.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - secunde»»\ - secundă - -minutes=\ - minut»»\ - minute - -hours=\ - ore»»\ - oră - -days=\ - zi»»\ - zile - -weeks=\ - săptămâni»»\ - săptămână - -months=\ - luni»»\ - lună - -years=\ - an»»\ - ani \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ru.properties b/timeago-parser/src/main/resources/i18n/time_units_ru.properties deleted file mode 100644 index 91e93cfe8..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ru.properties +++ /dev/null @@ -1,34 +0,0 @@ -seconds=\ - секунд»»\ - секунду»»\ - секунды»»\ - только что - -minutes=\ - минут»»\ - минуту»»\ - минуты - -hours=\ - час»»\ - часа»»\ - часов - -days=\ - день»»\ - дней»»\ - дня - -weeks=\ - Неделю»»\ - недели - -months=\ - месяц»»\ - месяца»»\ - месяцев - -years=\ - Год»»\ - года»»\ - лет \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_si.properties b/timeago-parser/src/main/resources/i18n/time_units_si.properties deleted file mode 100644 index 7c7cf38d4..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_si.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - තත්පර - -minutes=\ - මිනිත්තු - -hours=\ - පැය - -days=\ - දින - -weeks=\ - සති - -months=\ - මාස - -years=\ - වසර \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sk.properties b/timeago-parser/src/main/resources/i18n/time_units_sk.properties deleted file mode 100644 index 234554a7e..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sk.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - sekundami»»\ - sekundou - -minutes=\ - minútami»»\ - minútou - -hours=\ - hodinami»»\ - hodinou - -days=\ - dňami»»\ - dňom - -weeks=\ - týždňami»»\ - týždňom - -months=\ - mesiacmi»»\ - mesiacom - -years=\ - rokmi»»\ - rokom \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sl.properties b/timeago-parser/src/main/resources/i18n/time_units_sl.properties deleted file mode 100644 index 684928b3a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sl.properties +++ /dev/null @@ -1,34 +0,0 @@ -seconds=\ - sekundama»»\ - sekundami»»\ - sekundo - -minutes=\ - minutama»»\ - minutami»»\ - minuto - -hours=\ - urama»»\ - urami»»\ - uro - -days=\ - dnem»»\ - dnevi»»\ - dnevoma - -weeks=\ - tedni»»\ - tednom»»\ - tednoma - -months=\ - mesecem»»\ - mesecema»»\ - meseci - -years=\ - leti»»\ - letom»»\ - letoma \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sq.properties b/timeago-parser/src/main/resources/i18n/time_units_sq.properties deleted file mode 100644 index 02add95d1..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sq.properties +++ /dev/null @@ -1,23 +0,0 @@ -seconds=\ - sekonda»»\ - sekondë - -minutes=\ - minuta»»\ - minutë - -hours=\ - orë - -days=\ - ditë - -weeks=\ - javë - -months=\ - muaj - -years=\ - vit»»\ - vjet \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sr.properties b/timeago-parser/src/main/resources/i18n/time_units_sr.properties deleted file mode 100644 index 4549f052c..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sr.properties +++ /dev/null @@ -1,29 +0,0 @@ -seconds=\ - секунде»»\ - секунди - -minutes=\ - минута - -hours=\ - сат»»\ - сата»»\ - сати - -days=\ - дан»»\ - дана - -weeks=\ - недеље»»\ - недељу - -months=\ - месец»»\ - месеца»»\ - месеци - -years=\ - година»»\ - године»»\ - годину \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sr_Latn.properties b/timeago-parser/src/main/resources/i18n/time_units_sr_Latn.properties deleted file mode 100644 index ab4ad7f74..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sr_Latn.properties +++ /dev/null @@ -1,29 +0,0 @@ -seconds=\ - sekunde»»\ - sekundi - -minutes=\ - minuta - -hours=\ - sat»»\ - sati - -days=\ - dan»»\ - dana - -weeks=\ - nedelja»»\ - nedelje»»\ - nedelju - -months=\ - mesec»»\ - meseci»»\ - meseca - -years=\ - godine»»\ - godina»»\ - godinu \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sv.properties b/timeago-parser/src/main/resources/i18n/time_units_sv.properties deleted file mode 100644 index 0e9f75f5c..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sv.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - sekund»»\ - sekunder - -minutes=\ - minut»»\ - minuter - -hours=\ - timmar»»\ - timme - -days=\ - dag»»\ - dagar - -weeks=\ - vecka»»\ - veckor - -months=\ - månad»»\ - månader - -years=\ - år \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_sw.properties b/timeago-parser/src/main/resources/i18n/time_units_sw.properties deleted file mode 100644 index 99633ccab..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_sw.properties +++ /dev/null @@ -1,22 +0,0 @@ -seconds=\ - sekunde - -minutes=\ - dakika - -hours=\ - saa - -days=\ - siku - -weeks=\ - wiki - -months=\ - Mwezi»»\ - miezi - -years=\ - Miaka»»\ - Mwaka \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ta.properties b/timeago-parser/src/main/resources/i18n/time_units_ta.properties deleted file mode 100644 index e56412454..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ta.properties +++ /dev/null @@ -1,26 +0,0 @@ -seconds=\ - வினாடி»»\ - வினாடிகளுக்கு - -minutes=\ - நிமிடங்கள்»»\ - நிமிடம் - -hours=\ - மணிநேரத்திற்கு - -days=\ - நாட்களுக்கு»»\ - நாளுக்கு - -weeks=\ - வாரங்களுக்கு»»\ - வாரம் - -months=\ - மாதங்கள்»»\ - மாதம் - -years=\ - ஆண்டு»»\ - ஆண்டுகளுக்கு \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_te.properties b/timeago-parser/src/main/resources/i18n/time_units_te.properties deleted file mode 100644 index 4c7d55c6f..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_te.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - సెకను»»\ - సెకన్ల - -minutes=\ - నిమిషం»»\ - నిమిషాల - -hours=\ - గంట»»\ - గంటల - -days=\ - రోజు»»\ - రోజుల - -weeks=\ - వారం»»\ - వారాల - -months=\ - నెల»»\ - నెలల - -years=\ - సంవత్సరం»»\ - సంవత్సరాల \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_th.properties b/timeago-parser/src/main/resources/i18n/time_units_th.properties deleted file mode 100644 index 0b7df7fc6..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_th.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - วินาทีที่ผ่านมา - -minutes=\ - นาทีที่ผ่านมา - -hours=\ - ชั่วโมงที่ผ่านมา - -days=\ - วันที่ผ่านมา - -weeks=\ - สัปดาห์ที่ผ่านมา - -months=\ - เดือนที่ผ่านมา - -years=\ - ปีที่ผ่านมา \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_tr.properties b/timeago-parser/src/main/resources/i18n/time_units_tr.properties deleted file mode 100644 index b624a0180..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_tr.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - saniye - -minutes=\ - dakika - -hours=\ - saat - -days=\ - gün - -weeks=\ - hafta - -months=\ - ay - -years=\ - yıl \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_uk.properties b/timeago-parser/src/main/resources/i18n/time_units_uk.properties deleted file mode 100644 index dbda67f73..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_uk.properties +++ /dev/null @@ -1,33 +0,0 @@ -seconds=\ - секунд»»\ - секунди»»\ - секунду - -minutes=\ - хвилин»»\ - хвилини»»\ - хвилину - -hours=\ - годин»»\ - години»»\ - годину - -days=\ - день»»\ - дні»»\ - днів - -weeks=\ - тиждень»»\ - тижні - -months=\ - місяць»»\ - місяці»»\ - місяців - -years=\ - роки»»\ - років»»\ - рік \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_ur.properties b/timeago-parser/src/main/resources/i18n/time_units_ur.properties deleted file mode 100644 index 2a3cf03c3..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_ur.properties +++ /dev/null @@ -1,24 +0,0 @@ -seconds=\ - سیکنڈ»»\ - سیکنڈز - -minutes=\ - منٹ»»\ - منٹس - -hours=\ - گھنٹہ»»\ - گھنٹے - -days=\ - دن - -weeks=\ - ہفتہ»»\ - ہفتے - -months=\ - ماہ - -years=\ - سال \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_uz.properties b/timeago-parser/src/main/resources/i18n/time_units_uz.properties deleted file mode 100644 index 9ac9cfc3a..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_uz.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - soniya - -minutes=\ - daqiqa - -hours=\ - soat - -days=\ - kun - -weeks=\ - hafta - -months=\ - oy - -years=\ - yil \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_vi.properties b/timeago-parser/src/main/resources/i18n/time_units_vi.properties deleted file mode 100644 index 727c8370c..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_vi.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - giây - -minutes=\ - phút - -hours=\ - giờ - -days=\ - ngày - -weeks=\ - tuần - -months=\ - tháng - -years=\ - năm \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_zh_CN.properties b/timeago-parser/src/main/resources/i18n/time_units_zh_CN.properties deleted file mode 100644 index 8b3fa915f..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_zh_CN.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - 秒前 - -minutes=\ - 分钟前 - -hours=\ - 小时前 - -days=\ - 天前 - -weeks=\ - 周前 - -months=\ - 个月前 - -years=\ - 年前 \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_zh_HK.properties b/timeago-parser/src/main/resources/i18n/time_units_zh_HK.properties deleted file mode 100644 index 90ee56ee7..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_zh_HK.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - 秒前 - -minutes=\ - 分鐘前 - -hours=\ - 小時前 - -days=\ - 天前 - -weeks=\ - 週前 - -months=\ - 個月前 - -years=\ - 年前 \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_zh_TW.properties b/timeago-parser/src/main/resources/i18n/time_units_zh_TW.properties deleted file mode 100644 index 90ee56ee7..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_zh_TW.properties +++ /dev/null @@ -1,20 +0,0 @@ -seconds=\ - 秒前 - -minutes=\ - 分鐘前 - -hours=\ - 小時前 - -days=\ - 天前 - -weeks=\ - 週前 - -months=\ - 個月前 - -years=\ - 年前 \ No newline at end of file diff --git a/timeago-parser/src/main/resources/i18n/time_units_zu.properties b/timeago-parser/src/main/resources/i18n/time_units_zu.properties deleted file mode 100644 index 357e093ee..000000000 --- a/timeago-parser/src/main/resources/i18n/time_units_zu.properties +++ /dev/null @@ -1,27 +0,0 @@ -seconds=\ - amasekhondi»»\ - isekhondi - -minutes=\ - amaminithi»»\ - iminithi - -hours=\ - amahora»»\ - ihora - -days=\ - izinsuku»»\ - usuku - -weeks=\ - amaviki»»\ - iviki - -months=\ - inyanga»»\ - izinyanga - -years=\ - iminyaka»»\ - unyaka \ No newline at end of file From d8280ce0da0651165b54ed532517e14749ea037e Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 28 Apr 2019 17:03:17 -0300 Subject: [PATCH 3/9] [YouTube] Parse watching count in live streams items --- .../extractors/YoutubeStreamExtractor.java | 53 +++++++++++++++++++ .../YoutubeStreamInfoItemExtractor.java | 46 +++++++++++----- .../YoutubeStreamExtractorLivestreamTest.java | 2 +- 3 files changed, 86 insertions(+), 15 deletions(-) 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 242395371..092fd41ec 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 @@ -304,12 +304,65 @@ public class YoutubeStreamExtractor extends StreamExtractor { public long getViewCount() throws ParsingException { assertPageFetched(); try { + if (getStreamType().equals(StreamType.LIVE_STREAM)) { + return getLiveStreamWatchingCount(); + } + return Long.parseLong(doc.select("meta[itemprop=interactionCount]").attr(CONTENT)); } catch (Exception e) {//todo: find fallback method throw new ParsingException("Could not get number of views", e); } } + private long getLiveStreamWatchingCount() throws ExtractionException, IOException, JsonParserException { + // https://www.youtube.com/youtubei/v1/updated_metadata?alt=json&key= + String innerTubeKey = null, clientVersion = null; + if (playerArgs != null && !playerArgs.isEmpty()) { + innerTubeKey = playerArgs.getString("innertube_api_key"); + clientVersion = playerArgs.getString("innertube_context_client_version"); + } else if (!videoInfoPage.isEmpty()) { + innerTubeKey = videoInfoPage.get("innertube_api_key"); + clientVersion = videoInfoPage.get("innertube_context_client_version"); + } + + if (innerTubeKey == null || innerTubeKey.isEmpty()) { + throw new ExtractionException("Couldn't get innerTube key"); + } + + if (clientVersion == null || clientVersion.isEmpty()) { + throw new ExtractionException("Couldn't get innerTube client version"); + } + + final String metadataUrl = "https://www.youtube.com/youtubei/v1/updated_metadata?alt=json&key=" + innerTubeKey; + final byte[] dataBody = ("{\"context\":{\"client\":{\"clientName\":1,\"clientVersion\":\"" + clientVersion + "\"}}" + + ",\"videoId\":\"" + getId() + "\"}").getBytes("UTF-8"); + final Response response = getDownloader().execute(Request.newBuilder() + .post(metadataUrl, dataBody) + .addHeader("Content-Type", "application/json") + .build()); + final JsonObject jsonObject = JsonParser.object().from(response.responseBody()); + + for (Object actionEntry : jsonObject.getArray("actions")) { + if (!(actionEntry instanceof JsonObject)) continue; + final JsonObject entry = (JsonObject) actionEntry; + + final JsonObject updateViewershipAction = entry.getObject("updateViewershipAction", null); + if (updateViewershipAction == null) continue; + + final JsonArray viewCountRuns = JsonUtils.getArray(updateViewershipAction, "viewership.videoViewCountRenderer.viewCount.runs"); + if (viewCountRuns.isEmpty()) continue; + + final JsonObject textObject = viewCountRuns.getObject(0); + if (!textObject.has("text")) { + throw new ExtractionException("Response don't have \"text\" element"); + } + + return Long.parseLong(Utils.removeNonDigitCharacters(textObject.getString("text"))); + } + + throw new ExtractionException("Could not find correct results in response"); + } + @Override public long getLikeCount() throws ParsingException { assertPageFetched(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 162e2e49f..46afe7ab0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -3,10 +3,10 @@ package org.schabi.newpipe.extractor.services.youtube.extractors; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; -import org.schabi.newpipe.extractor.localization.TimeAgoParser; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nullable; @@ -141,6 +141,10 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { @Override public String getTextualUploadDate() throws ParsingException { + if (getStreamType().equals(StreamType.LIVE_STREAM)) { + return null; + } + if (cachedUploadDate != null) { return cachedUploadDate; } @@ -160,9 +164,12 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { @Override public Calendar getUploadDate() throws ParsingException { + if (getStreamType().equals(StreamType.LIVE_STREAM)) { + return null; + } + String textualUploadDate = getTextualUploadDate(); - if (timeAgoParser != null - && textualUploadDate != null && !"".equals(textualUploadDate)) { + if (timeAgoParser != null && textualUploadDate != null && !textualUploadDate.isEmpty()) { return timeAgoParser.parse(textualUploadDate); } else { return null; @@ -172,24 +179,35 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { @Override public long getViewCount() throws ParsingException { String input; - try { - // TODO: Return the actual live stream's watcher count - // -1 for no view count - if (getStreamType() == StreamType.LIVE_STREAM) return -1; - Element meta = item.select("div[class=\"yt-lockup-meta\"]").first(); - if (meta == null) return -1; + if (getStreamType().equals(StreamType.LIVE_STREAM)) { + Element meta = item.select("ul[class=\"yt-lockup-meta-info\"]").first(); + if (meta == null) return 0; - // This case can happen if google releases a special video - if(meta.select("li").size() < 2) return -1; + final Elements li = meta.select("li"); + if (li.isEmpty()) return 0; - input = meta.select("li").get(1).text(); + input = li.first().text(); + } else { + try { + Element meta = item.select("div[class=\"yt-lockup-meta\"]").first(); + if (meta == null) return -1; - } catch (IndexOutOfBoundsException e) { - throw new ParsingException("Could not parse yt-lockup-meta although available: " + getUrl(), e); + // This case can happen if google releases a special video + if (meta.select("li").size() < 2) return -1; + + input = meta.select("li").get(1).text(); + } catch (IndexOutOfBoundsException e) { + throw new ParsingException("Could not parse yt-lockup-meta although available: " + getUrl(), e); + } + } + + if (input == null) { + throw new ParsingException("Input is null"); } try { + return Long.parseLong(Utils.removeNonDigitCharacters(input)); } catch (NumberFormatException e) { // if this happens the video probably has no views diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java index 408c29a3f..eb2541edf 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorLivestreamTest.java @@ -68,7 +68,7 @@ public class YoutubeStreamExtractorLivestreamTest { @Test public void testGetViewCount() throws ParsingException { long count = extractor.getViewCount(); - assertTrue(Long.toString(count), count >= 7148995); + assertTrue(Long.toString(count), count > -1); } @Test From cb1e327a6e1f779fb7b1ed2bc8f454280949102d Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 28 Apr 2019 17:03:18 -0300 Subject: [PATCH 4/9] [YouTube] Fix parsing of video reminders --- .../extractors/YoutubeStreamExtractor.java | 13 ----- .../YoutubeStreamInfoItemExtractor.java | 54 +++++++++++++++++-- 2 files changed, 51 insertions(+), 16 deletions(-) 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 092fd41ec..7bafff098 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 @@ -1038,19 +1038,6 @@ public class YoutubeStreamExtractor extends StreamExtractor { return ""; } - @Override - public long getViewCount() throws ParsingException { - try { - if (getStreamType() == StreamType.LIVE_STREAM) return -1; - - return Long.parseLong(Utils.removeNonDigitCharacters( - li.select("span.view-count").first().text())); - } catch (Exception e) { - //related videos sometimes have no view count - return 0; - } - } - @Override public String getThumbnailUrl() throws ParsingException { Element img = li.select("img").first(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 46afe7ab0..98a484d3a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -10,7 +10,9 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nullable; +import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Date; /* * Copyright (C) Christian Schabesberger 2016 @@ -150,6 +152,15 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { } try { + if (isVideoReminder()) { + final Calendar calendar = getDateFromReminder(); + if (calendar != null) { + return cachedUploadDate = new SimpleDateFormat("yyyy-MM-dd HH:mm") + .format(calendar.getTime()); + } + } + + Element meta = item.select("div[class=\"yt-lockup-meta\"]").first(); if (meta == null) return ""; @@ -168,6 +179,13 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { return null; } + if (isVideoReminder()) { + final Calendar calendar = getDateFromReminder(); + if (calendar != null) { + return calendar; + } + } + String textualUploadDate = getTextualUploadDate(); if (timeAgoParser != null && textualUploadDate != null && !textualUploadDate.isEmpty()) { return timeAgoParser.parse(textualUploadDate); @@ -180,8 +198,12 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { public long getViewCount() throws ParsingException { String input; - if (getStreamType().equals(StreamType.LIVE_STREAM)) { - Element meta = item.select("ul[class=\"yt-lockup-meta-info\"]").first(); + final Element spanViewCount = item.select("span.view-count").first(); + if (spanViewCount != null) { + input = spanViewCount.text(); + + } else if (getStreamType().equals(StreamType.LIVE_STREAM)) { + Element meta = item.select("ul.yt-lockup-meta-info").first(); if (meta == null) return 0; final Elements li = meta.select("li"); @@ -190,7 +212,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { input = li.first().text(); } else { try { - Element meta = item.select("div[class=\"yt-lockup-meta\"]").first(); + Element meta = item.select("div.yt-lockup-meta").first(); if (meta == null) return -1; // This case can happen if google releases a special video @@ -238,6 +260,32 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { } } + + private boolean isVideoReminder() { + return !item.select("span.yt-uix-livereminder").isEmpty(); + } + + private Calendar getDateFromReminder() throws ParsingException { + final Element timeFuture = item.select("span.yt-badge.localized-date").first(); + + if (timeFuture == null) { + throw new ParsingException("Span timeFuture is null"); + } + + final String timestamp = timeFuture.attr("data-timestamp"); + if (!timestamp.isEmpty()) { + try { + final Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(Long.parseLong(timestamp) * 1000L)); + return calendar; + } catch (Exception e) { + throw new ParsingException("Could not parse = \"" + timestamp + "\""); + } + } + + throw new ParsingException("Could not parse date from reminder element: \"" + timeFuture + "\""); + } + /** * Generic method that checks if the element contains any clues that it's a livestream item */ From b42bebdee8fe42cf2e34f184f59a0b80e8e1cdf7 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 28 Apr 2019 17:03:19 -0300 Subject: [PATCH 5/9] Add instructions to quickly test changes in the extractor - Make use of the local Maven repository --- README.md | 11 +++++++++++ build.gradle | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/README.md b/README.md index 715ec2fb8..3cf4e4c5b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,17 @@ If you're using Gradle, you could add NewPipe Extractor as a dependency with the 1. Add `maven { url 'https://jitpack.io' }` to the `repositories` in your `build.gradle`. 2. Add `compile 'com.github.TeamNewPipe:NewPipeExtractor:v0.11.0'`the `dependencies` in your `build.gradle`. Replace `v0.11.0` with the latest release. +### Testing changes + +To test changes quickly you can build the library locally. Using the local Maven repository is a good approach, here's a gist of how to use it: + +1. Add `mavenLocal()` in your project `repositories` list (usually as the first entry to give priority above the others). +2. It's _recommended_ that you change the `version` of this library (e.g. `LOCAL_SNAPSHOT`). +3. Run gradle's `ìnstall` task to deploy this library to your local repository (using the wrapper, present in the root of this project: `./gradlew install`) +4. Change the dependency version used in your project to match the one you chose in step 2 (`implementation 'com.github.TeamNewPipe:NewPipeExtractor:LOCAL_SNAPSHOT'`) + +> Tip for Android Studio users: After you make changes and run the `install` task, use the menu option `File → "Sync with File System"` to refresh the library in your project. + ## Supported sites The following sites are currently supported: diff --git a/build.gradle b/build.gradle index 9f25fc28e..b0cdf7114 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,23 @@ allprojects { apply plugin: 'java-library' + apply plugin: 'maven' + sourceCompatibility = 1.7 targetCompatibility = 1.7 version 'v0.13.0' + group 'com.github.TeamNewPipe' repositories { jcenter() } } +dependencies { + implementation project(':extractor') + implementation project(':timeago-parser') +} + subprojects { task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' From 41b51adceb517f852abf80c10e82e90b13ded098 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Wed, 2 Oct 2019 02:03:06 -0300 Subject: [PATCH 6/9] [YouTube] Force english as the only supported language (#196) --- .../newpipe/extractor/services/youtube/YoutubeService.java | 5 +++-- .../services/youtube/extractors/YoutubeChannelExtractor.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java index 279a85130..ec728e53e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java @@ -139,13 +139,14 @@ public class YoutubeService extends StreamingService { // https://www.youtube.com/picker_ajax?action_language_json=1 private static final List SUPPORTED_LANGUAGES = Localization.listFrom( - "af", "am", "ar", "az", "be", "bg", "bn", "bs", "ca", "cs", "da", "de", + "en-GB" + /*"af", "am", "ar", "az", "be", "bg", "bn", "bs", "ca", "cs", "da", "de", "el", "en", "en-GB", "es", "es-419", "es-US", "et", "eu", "fa", "fi", "fil", "fr", "fr-CA", "gl", "gu", "hi", "hr", "hu", "hy", "id", "is", "it", "iw", "ja", "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", "mn", "mr", "ms", "my", "ne", "nl", "no", "pa", "pl", "pt", "pt-PT", "ro", "ru", "si", "sk", "sl", "sq", "sr", "sr-Latn", "sv", "sw", "ta", "te", "th", "tr", - "uk", "ur", "uz", "vi", "zh-CN", "zh-HK", "zh-TW", "zu" + "uk", "ur", "uz", "vi", "zh-CN", "zh-HK", "zh-TW", "zu"*/ ); // https://www.youtube.com/picker_ajax?action_country_json=1 diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java index 3ba53bc2f..adc4705e4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java @@ -47,7 +47,7 @@ import java.io.IOException; public class YoutubeChannelExtractor extends ChannelExtractor { /*package-private*/ static final String CHANNEL_URL_BASE = "https://www.youtube.com/channel/"; private static final String CHANNEL_FEED_BASE = "https://www.youtube.com/feeds/videos.xml?channel_id="; - private static final String CHANNEL_URL_PARAMETERS = "/videos?view=0&flow=list&sort=dd&live_view=10000&gl=US&hl=en"; + private static final String CHANNEL_URL_PARAMETERS = "/videos?view=0&flow=list&sort=dd&live_view=10000"; private Document doc; From 6ca4c8986a7cb7767b415b533b024f061e05dc34 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 6 Oct 2019 16:40:08 -0300 Subject: [PATCH 7/9] Temp Commit: Ignore Test (Remove this before merge) --- .../services/youtube/search/YoutubeSearchCountTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java index c9568045a..9838390cb 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.extractor.services.youtube.search; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; @@ -26,6 +27,7 @@ public class YoutubeSearchCountTest { itemsPage = extractor.getInitialPage(); } + @Ignore("The subscriber count was removed from the old interface that NewPipe fetches the content from, ignoring it for now.") @Test public void testViewCount() { ChannelInfoItem ci = (ChannelInfoItem) itemsPage.getItems().get(0); From 3d21ef5dba2c99ec533969e6c681809de62e70e7 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 3 Nov 2019 15:45:25 -0300 Subject: [PATCH 8/9] Introduce class that indicates when the time ago is an approximation --- .../extractor/comments/CommentsInfoItem.java | 10 +++-- .../comments/CommentsInfoItemExtractor.java | 6 ++- .../extractor/localization/DateWrapper.java | 39 +++++++++++++++++++ .../extractor/localization/TimeAgoParser.java | 36 ++++++++++------- .../extractors/MediaCCCStreamExtractor.java | 9 ++--- .../MediaCCCStreamInfoItemExtractor.java | 9 +++-- .../soundcloud/SoundcloudStreamExtractor.java | 7 ++-- .../SoundcloudStreamInfoItemExtractor.java | 7 ++-- .../YoutubeCommentsInfoItemExtractor.java | 6 ++- .../extractors/YoutubeStreamExtractor.java | 5 ++- .../YoutubeStreamInfoItemExtractor.java | 10 ++--- .../extractor/stream/StreamExtractor.java | 5 +-- .../newpipe/extractor/stream/StreamInfo.java | 16 ++++---- .../extractor/stream/StreamInfoItem.java | 16 ++------ .../stream/StreamInfoItemExtractor.java | 12 +++--- .../extractor/services/DefaultTests.java | 5 ++- .../MediaCCCStreamExtractorTest.java | 3 +- .../SoundcloudStreamExtractorDefaultTest.java | 3 +- .../YoutubeChannelLocalizationTest.java | 15 +++---- ...utubeStreamExtractorAgeRestrictedTest.java | 5 +-- ...utubeStreamExtractorControversialTest.java | 3 +- .../YoutubeStreamExtractorDefaultTest.java | 4 +- 22 files changed, 139 insertions(+), 92 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/localization/DateWrapper.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java index 7e225026e..6d6290716 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItem.java @@ -1,8 +1,9 @@ package org.schabi.newpipe.extractor.comments; import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.localization.DateWrapper; -import java.util.Calendar; +import javax.annotation.Nullable; public class CommentsInfoItem extends InfoItem { @@ -12,7 +13,7 @@ public class CommentsInfoItem extends InfoItem { private String authorThumbnail; private String authorEndpoint; private String textualPublishedTime; - private Calendar publishedTime; + @Nullable private DateWrapper publishedTime; private int likeCount; public CommentsInfoItem(int serviceId, String url, String name) { @@ -67,11 +68,12 @@ public class CommentsInfoItem extends InfoItem { this.textualPublishedTime = textualPublishedTime; } - public Calendar getPublishedTime() { + @Nullable + public DateWrapper getPublishedTime() { return publishedTime; } - public void setPublishedTime(Calendar publishedTime) { + public void setPublishedTime(@Nullable DateWrapper publishedTime) { this.publishedTime = publishedTime; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java index 4560f0441..7b40f8fa6 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/comments/CommentsInfoItemExtractor.java @@ -2,8 +2,9 @@ package org.schabi.newpipe.extractor.comments; import org.schabi.newpipe.extractor.InfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.DateWrapper; -import java.util.Calendar; +import javax.annotation.Nullable; public interface CommentsInfoItemExtractor extends InfoItemExtractor { String getCommentId() throws ParsingException; @@ -12,6 +13,7 @@ public interface CommentsInfoItemExtractor extends InfoItemExtractor { String getAuthorThumbnail() throws ParsingException; String getAuthorEndpoint() throws ParsingException; String getTextualPublishedTime() throws ParsingException; - Calendar getPublishedTime() throws ParsingException; + @Nullable + DateWrapper getPublishedTime() throws ParsingException; int getLikeCount() throws ParsingException; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/DateWrapper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/DateWrapper.java new file mode 100644 index 000000000..433287852 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/DateWrapper.java @@ -0,0 +1,39 @@ +package org.schabi.newpipe.extractor.localization; + +import edu.umd.cs.findbugs.annotations.NonNull; + +import java.io.Serializable; +import java.util.Calendar; + +/** + * A wrapper class that provides a field to describe if the date is precise or just an approximation. + */ +public class DateWrapper implements Serializable { + @NonNull private final Calendar date; + private final boolean isApproximation; + + public DateWrapper(@NonNull Calendar date) { + this(date, false); + } + + public DateWrapper(@NonNull Calendar date, boolean isApproximation) { + this.date = date; + this.isApproximation = isApproximation; + } + + /** + * @return the wrapped date. + */ + @NonNull + public Calendar date() { + return date; + } + + /** + * @return if the date is considered is precise or just an approximation (e.g. service only returns an approximation + * like 2 weeks ago instead of a precise date). + */ + public boolean isApproximation() { + return isApproximation; + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java index 3d2e99237..aae9b14c4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java @@ -31,15 +31,16 @@ public class TimeAgoParser { } /** - * Parses a textual date in the format '2 days ago' into a Calendar representation. - * Beginning with weeks ago, marks the date as approximated by setting minutes, seconds - * and milliseconds to 0. + * Parses a textual date in the format '2 days ago' into a Calendar representation which is then wrapped in a + * {@link DateWrapper} object. + *

+ * Beginning with days ago, the date is considered as an approximation. * * @param textualDate The original date as provided by the streaming service - * @return The parsed (approximated) time + * @return The parsed time (can be approximated) * @throws ParsingException if the time unit could not be recognized */ - public Calendar parse(String textualDate) throws ParsingException { + public DateWrapper parse(String textualDate) throws ParsingException { for (Map.Entry> caseUnitEntry : patternsHolder.specialCases().entrySet()) { final TimeAgoUnit timeAgoUnit = caseUnitEntry.getKey(); for (Map.Entry caseMapToAmountEntry : caseUnitEntry.getValue().entrySet()) { @@ -47,7 +48,7 @@ public class TimeAgoParser { final Integer caseAmount = caseMapToAmountEntry.getValue(); if (textualDateMatches(textualDate, caseText)) { - return getCalendar(caseAmount, timeAgoUnit); + return getResultFor(caseAmount, timeAgoUnit); } } } @@ -61,8 +62,8 @@ public class TimeAgoParser { timeAgoAmount = 1; } - TimeAgoUnit timeAgoUnit = parseTimeAgoUnit(textualDate); - return getCalendar(timeAgoAmount, timeAgoUnit); + final TimeAgoUnit timeAgoUnit = parseTimeAgoUnit(textualDate); + return getResultFor(timeAgoAmount, timeAgoUnit); } private int parseTimeAgoAmount(String textualDate) throws NumberFormatException { @@ -110,8 +111,9 @@ public class TimeAgoParser { } } - private Calendar getCalendar(int timeAgoAmount, TimeAgoUnit timeAgoUnit) { - Calendar calendarTime = getNow(); + private DateWrapper getResultFor(int timeAgoAmount, TimeAgoUnit timeAgoUnit) { + final Calendar calendarTime = getNow(); + boolean isApproximation = false; switch (timeAgoUnit) { case SECONDS: @@ -128,28 +130,32 @@ public class TimeAgoParser { case DAYS: calendarTime.add(Calendar.DAY_OF_MONTH, -timeAgoAmount); - markApproximatedTime(calendarTime); + isApproximation = true; break; case WEEKS: calendarTime.add(Calendar.WEEK_OF_YEAR, -timeAgoAmount); - markApproximatedTime(calendarTime); + isApproximation = true; break; case MONTHS: calendarTime.add(Calendar.MONTH, -timeAgoAmount); - markApproximatedTime(calendarTime); + isApproximation = true; break; case YEARS: calendarTime.add(Calendar.YEAR, -timeAgoAmount); // Prevent `PrettyTime` from showing '12 months ago'. calendarTime.add(Calendar.DAY_OF_MONTH, -1); - markApproximatedTime(calendarTime); + isApproximation = true; break; } - return calendarTime; + if (isApproximation) { + markApproximatedTime(calendarTime); + } + + return new DateWrapper(calendarTime, isApproximation); } private Calendar getNow() { 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 16e5e0d52..a1dfd2454 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 @@ -10,15 +10,12 @@ import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.*; import javax.annotation.Nonnull; import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; import java.util.List; public class MediaCCCStreamExtractor extends StreamExtractor { @@ -38,8 +35,8 @@ public class MediaCCCStreamExtractor extends StreamExtractor { @Nonnull @Override - public Calendar getUploadDate() throws ParsingException { - return MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate()); + public DateWrapper getUploadDate() throws ParsingException { + return new DateWrapper(MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate())); } @Nonnull diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java index 085c115b8..76347b39b 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java @@ -2,11 +2,12 @@ package org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems; import com.grack.nanojson.JsonObject; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; -import java.util.Calendar; +import javax.annotation.Nullable; public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor { @@ -47,14 +48,16 @@ public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor return event.getString("conference_url"); } + @Nullable @Override public String getTextualUploadDate() throws ParsingException { return event.getString("release_date"); } + @Nullable @Override - public Calendar getUploadDate() throws ParsingException { - return MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate()); + public DateWrapper getUploadDate() throws ParsingException { + return new DateWrapper(MediaCCCParsingHelper.parseDateFrom(getTextualUploadDate())); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java index 0fa636e7f..c9c44c991 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java @@ -9,15 +9,14 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.*; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; -import java.util.Calendar; import java.util.Collections; import java.util.List; @@ -58,8 +57,8 @@ public class SoundcloudStreamExtractor extends StreamExtractor { @Nonnull @Override - public Calendar getUploadDate() throws ParsingException { - return SoundcloudParsingHelper.parseDate(getTextualUploadDate()); + public DateWrapper getUploadDate() throws ParsingException { + return new DateWrapper(SoundcloudParsingHelper.parseDate(getTextualUploadDate())); } @Nonnull diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java index 7453c5ada..da0ca1b54 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java @@ -2,11 +2,10 @@ package org.schabi.newpipe.extractor.services.soundcloud; import com.grack.nanojson.JsonObject; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; -import java.util.Calendar; - import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps; public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtractor { @@ -48,8 +47,8 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto } @Override - public Calendar getUploadDate() throws ParsingException { - return SoundcloudParsingHelper.parseDate(getTextualUploadDate()); + public DateWrapper getUploadDate() throws ParsingException { + return new DateWrapper(SoundcloudParsingHelper.parseDate(getTextualUploadDate())); } private String getCreatedAt() { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java index f3e6df2a4..3fa0e388e 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeCommentsInfoItemExtractor.java @@ -5,10 +5,11 @@ import com.grack.nanojson.JsonObject; import org.schabi.newpipe.extractor.comments.CommentsInfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.TimeAgoParser; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.Utils; -import java.util.Calendar; +import javax.annotation.Nullable; public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtractor { @@ -55,8 +56,9 @@ public class YoutubeCommentsInfoItemExtractor implements CommentsInfoItemExtract } } + @Nullable @Override - public Calendar getPublishedTime() throws ParsingException { + public DateWrapper getPublishedTime() throws ParsingException { String textualPublishedTime = getTextualPublishedTime(); if (timeAgoParser != null && textualPublishedTime != null && !textualPublishedTime.isEmpty()) { return timeAgoParser.parse(textualPublishedTime); 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 7bafff098..671db465d 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 @@ -23,6 +23,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.extractor.localization.TimeAgoParser; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.services.youtube.ItagItem; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.*; @@ -134,14 +135,14 @@ public class YoutubeStreamExtractor extends StreamExtractor { } @Override - public Calendar getUploadDate() throws ParsingException { + public DateWrapper getUploadDate() throws ParsingException { final String textualUploadDate = getTextualUploadDate(); if (textualUploadDate == null) { return null; } - return YoutubeParsingHelper.parseDateFrom(textualUploadDate); + return new DateWrapper(YoutubeParsingHelper.parseDateFrom(textualUploadDate)); } @Nonnull diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java index 98a484d3a..514b4fb0a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java @@ -4,6 +4,7 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.TimeAgoParser; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; @@ -141,6 +142,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { } } + @Nullable @Override public String getTextualUploadDate() throws ParsingException { if (getStreamType().equals(StreamType.LIVE_STREAM)) { @@ -173,17 +175,15 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { } } + @Nullable @Override - public Calendar getUploadDate() throws ParsingException { + public DateWrapper getUploadDate() throws ParsingException { if (getStreamType().equals(StreamType.LIVE_STREAM)) { return null; } if (isVideoReminder()) { - final Calendar calendar = getDateFromReminder(); - if (calendar != null) { - return calendar; - } + return new DateWrapper(getDateFromReminder()); } String textualUploadDate = getTextualUploadDate(); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java index 7957de2a5..d697dff2c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java @@ -26,13 +26,12 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.utils.Parser; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; import java.util.Collections; import java.util.List; @@ -72,7 +71,7 @@ public abstract class StreamExtractor extends Extractor { * @see #getTextualUploadDate() */ @Nullable - public abstract Calendar getUploadDate() throws ParsingException; + public abstract DateWrapper getUploadDate() throws ParsingException; /** * This will return the url to the thumbnail of the stream. Try to return the medium resolution here. diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java index 8a049faa0..34ea703c2 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java @@ -1,19 +1,19 @@ package org.schabi.newpipe.extractor.stream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - import org.schabi.newpipe.extractor.Info; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.utils.DashMpdParser; import org.schabi.newpipe.extractor.utils.ExtractorHelper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /* * Created by Christian Schabesberger on 26.08.15. * @@ -278,7 +278,7 @@ public class StreamInfo extends Info { private StreamType streamType; private String thumbnailUrl = ""; private String textualUploadDate; - private Calendar uploadDate; + private DateWrapper uploadDate; private long duration = -1; private int ageLimit = -1; private String description; @@ -342,11 +342,11 @@ public class StreamInfo extends Info { this.textualUploadDate = textualUploadDate; } - public Calendar getUploadDate() { + public DateWrapper getUploadDate() { return uploadDate; } - public void setUploadDate(Calendar uploadDate) { + public void setUploadDate(DateWrapper uploadDate) { this.uploadDate = uploadDate; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java index 202188a79..6623c1efe 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItem.java @@ -21,9 +21,9 @@ package org.schabi.newpipe.extractor.stream; */ import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.localization.DateWrapper; import javax.annotation.Nullable; -import java.util.Calendar; /** * Info object for previews of unopened videos, eg search results, related videos @@ -33,7 +33,7 @@ public class StreamInfoItem extends InfoItem { private String uploaderName; private String textualUploadDate; - private Calendar uploadDate; + @Nullable private DateWrapper uploadDate; private long viewCount = -1; private long duration = -1; @@ -80,10 +80,6 @@ public class StreamInfoItem extends InfoItem { this.uploaderUrl = uploaderUrl; } - /** - * @return The original textual upload date as returned by the streaming service. - * @see #getUploadDate() - */ @Nullable public String getTextualUploadDate() { return textualUploadDate; @@ -93,16 +89,12 @@ public class StreamInfoItem extends InfoItem { this.textualUploadDate = uploadDate; } - /** - * @return The (approximated) date and time this item was uploaded or {@code null}. - * @see #getTextualUploadDate() - */ @Nullable - public Calendar getUploadDate() { + public DateWrapper getUploadDate() { return uploadDate; } - public void setUploadDate(Calendar uploadDate) { + public void setUploadDate(@Nullable DateWrapper uploadDate) { this.uploadDate = uploadDate; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java index 154e74651..113f3a87f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemExtractor.java @@ -2,8 +2,9 @@ package org.schabi.newpipe.extractor.stream; import org.schabi.newpipe.extractor.InfoItemExtractor; import org.schabi.newpipe.extractor.exceptions.ParsingException; +import org.schabi.newpipe.extractor.localization.DateWrapper; -import java.util.Calendar; +import javax.annotation.Nullable; /* * Created by Christian Schabesberger on 28.02.16. @@ -69,26 +70,27 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor { * The original textual date provided by the service. Should be used as a fallback if * {@link #getUploadDate()} isn't provided by the service, or it fails for some reason. * - * @return The original textual date provided by the service. + * @return The original textual date provided by the service or {@code null} if not provided. * @throws ParsingException if there is an error in the extraction * @see #getUploadDate() */ + @Nullable String getTextualUploadDate() throws ParsingException; /** * Extracts the upload date and time of this item and parses it. *

* If the service doesn't provide an exact time, an approximation can be returned. - * The approximation should be marked by setting seconds and milliseconds to zero. *
* If the service doesn't provide any date at all, then {@code null} should be returned. *

* - * @return The (approximated) date and time this item was uploaded or {@code null}. + * @return The date and time (can be approximated) this item was uploaded or {@code null}. * @throws ParsingException if there is an error in the extraction * or the extracted date couldn't be parsed. * @see #getTextualUploadDate() */ - Calendar getUploadDate() throws ParsingException; + @Nullable + DateWrapper getUploadDate() throws ParsingException; } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java index 3b839fd89..8cf27094a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultTests.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.extractor.services; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import java.util.Calendar; @@ -31,9 +32,9 @@ public final class DefaultTests { final String textualUploadDate = streamInfoItem.getTextualUploadDate(); if (textualUploadDate != null && !textualUploadDate.isEmpty()) { - final Calendar uploadDate = streamInfoItem.getUploadDate(); + final DateWrapper uploadDate = streamInfoItem.getUploadDate(); assertNotNull("No parsed upload date", uploadDate); - assertTrue("Upload date not in the past", uploadDate.before(Calendar.getInstance())); + assertTrue("Upload date not in the past", uploadDate.date().before(Calendar.getInstance())); } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java index 9aa1ef025..befd840f4 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCStreamExtractorTest.java @@ -14,6 +14,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; +import static java.util.Objects.requireNonNull; import static junit.framework.TestCase.assertEquals; import static org.schabi.newpipe.extractor.ServiceList.MediaCCC; @@ -95,6 +96,6 @@ public class MediaCCCStreamExtractorTest implements BaseExtractorTest { public void testGetUploadDate() throws ParsingException, ParseException { final Calendar instance = Calendar.getInstance(); instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2018-05-11")); - Assert.assertEquals(instance, extractor.getUploadDate()); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java index 9610a43af..8a3883fd6 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java @@ -16,6 +16,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; +import static java.util.Objects.requireNonNull; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; @@ -80,7 +81,7 @@ public class SoundcloudStreamExtractorDefaultTest { public void testGetUploadDate() throws ParsingException, ParseException { final Calendar instance = Calendar.getInstance(); instance.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse("2016/07/31 18:18:07 +0000")); - Assert.assertEquals(instance, extractor.getUploadDate()); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java index 731225af2..29f3d0323 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLocalizationTest.java @@ -7,6 +7,7 @@ import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.localization.Localization; +import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import java.text.SimpleDateFormat; @@ -61,9 +62,9 @@ public class YoutubeChannelLocalizationTest { String debugMessage = "[" + String.format("%02d", i) + "] " + currentLocalization.getLocalizationCode() + " → " + item.getName() + "\n:::: " + item.getStreamType() + ", views = " + item.getViewCount(); - final Calendar uploadDate = item.getUploadDate(); + final DateWrapper uploadDate = item.getUploadDate(); if (uploadDate != null) { - String dateAsText = dateFormat.format(uploadDate.getTime()); + String dateAsText = dateFormat.format(uploadDate.date().getTime()); debugMessage += "\n:::: " + item.getTextualUploadDate() + "\n:::: " + dateAsText; } @@ -102,17 +103,17 @@ public class YoutubeChannelLocalizationTest { final StreamInfoItem referenceItem = referenceList.get(i); final StreamInfoItem currentItem = currentList.get(i); - final Calendar referenceUploadDate = referenceItem.getUploadDate(); - final Calendar currentUploadDate = currentItem.getUploadDate(); + final DateWrapper referenceUploadDate = referenceItem.getUploadDate(); + final DateWrapper currentUploadDate = currentItem.getUploadDate(); final String referenceDateString = referenceUploadDate == null ? "null" : - dateFormat.format(referenceUploadDate.getTime()); + dateFormat.format(referenceUploadDate.date().getTime()); final String currentDateString = currentUploadDate == null ? "null" : - dateFormat.format(currentUploadDate.getTime()); + dateFormat.format(currentUploadDate.date().getTime()); long difference = -1; if (referenceUploadDate != null && currentUploadDate != null) { - difference = Math.abs(referenceUploadDate.getTimeInMillis() - currentUploadDate.getTimeInMillis()); + difference = Math.abs(referenceUploadDate.date().getTimeInMillis() - currentUploadDate.date().getTimeInMillis()); } final boolean areTimeEquals = difference < 5 * 60 * 1000L; diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java index c626651aa..992a8cd92 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorAgeRestrictedTest.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.extractor.services.youtube.stream; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.MediaFormat; @@ -18,9 +17,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.List; +import static java.util.Objects.requireNonNull; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ServiceList.YouTube; @@ -93,7 +92,7 @@ public class YoutubeStreamExtractorAgeRestrictedTest { public void testGetUploadDate() throws ParsingException, ParseException { final Calendar instance = Calendar.getInstance(); instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2017-01-25")); - assertEquals(instance, extractor.getUploadDate()); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java index 214f6beca..7faec8051 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorControversialTest.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import static java.util.Objects.requireNonNull; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ServiceList.YouTube; @@ -92,7 +93,7 @@ public class YoutubeStreamExtractorControversialTest { public void testGetUploadDate() throws ParsingException, ParseException { final Calendar instance = Calendar.getInstance(); instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2010-09-09")); - assertEquals(instance, extractor.getUploadDate()); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); } @Test diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java index 27638efe9..e715144a9 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java @@ -17,9 +17,9 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; -import java.util.Date; import java.util.List; +import static java.util.Objects.*; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ServiceList.YouTube; @@ -119,7 +119,7 @@ public class YoutubeStreamExtractorDefaultTest { public void testGetUploadDate() throws ParsingException, ParseException { final Calendar instance = Calendar.getInstance(); instance.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("2015-10-22")); - Assert.assertEquals(instance, extractor.getUploadDate()); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); } @Test From 0c6e2c8f2356213843e7b04d6a55eb0f7099fa79 Mon Sep 17 00:00:00 2001 From: Mauricio Colli Date: Sun, 6 Oct 2019 16:40:08 -0300 Subject: [PATCH 9/9] Revert "Temp Commit: Ignore Test (Remove this before merge)" This reverts commit 6ca4c8986a7cb7767b415b533b024f061e05dc34. --- .../services/youtube/search/YoutubeSearchCountTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java index 9838390cb..c9568045a 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchCountTest.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.extractor.services.youtube.search; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; @@ -27,7 +26,6 @@ public class YoutubeSearchCountTest { itemsPage = extractor.getInitialPage(); } - @Ignore("The subscriber count was removed from the old interface that NewPipe fetches the content from, ignoring it for now.") @Test public void testViewCount() { ChannelInfoItem ci = (ChannelInfoItem) itemsPage.getItems().get(0);