From 0261e637d31ab495599f0c56f5e071b3f7dbf0db Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Fri, 12 Jul 2024 08:24:03 +0530 Subject: [PATCH] Extract stream duration as a Java 8 Duration --- .../BandcampRadioInfoItemExtractor.java | 9 ++++---- ...campDiscographStreamInfoItemExtractor.java | 5 ---- ...ndcampPlaylistStreamInfoItemExtractor.java | 6 +++-- ...BandcampSearchStreamInfoItemExtractor.java | 5 ---- .../MediaCCCLiveStreamKioskExtractor.java | 5 ---- .../extractors/MediaCCCRecentKiosk.java | 2 +- .../MediaCCCRecentKioskExtractor.java | 6 +++-- .../MediaCCCStreamInfoItemExtractor.java | 6 +++-- .../PeertubeStreamInfoItemExtractor.java | 6 +++-- .../SoundcloudStreamInfoItemExtractor.java | 6 +++-- .../youtube/YoutubeParsingHelper.java | 23 +++++++++---------- .../YoutubeFeedInfoItemExtractor.java | 6 ----- ...tubeMusicSongOrVideoInfoItemExtractor.java | 4 +++- .../YoutubeReelInfoItemExtractor.java | 6 ----- .../YoutubeStreamInfoItemExtractor.java | 9 ++++---- .../extractor/stream/StreamInfoItem.java | 17 +++++++++++--- .../stream/StreamInfoItemExtractor.java | 20 +++++++++++++--- .../stream/StreamInfoItemsCollector.java | 6 ++--- .../newpipe/extractor/ExtractorAsserts.java | 10 ++++---- .../MediaCCCRecentListExtractorTest.java | 7 +++--- .../youtube/YoutubeParsingHelperTest.java | 10 +++++--- 21 files changed, 94 insertions(+), 80 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampRadioInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampRadioInfoItemExtractor.java index 023234aa3..465707b78 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampRadioInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampRadioInfoItemExtractor.java @@ -11,7 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamType; import javax.annotation.Nonnull; import javax.annotation.Nullable; - +import java.time.Duration; import java.util.List; import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.BASE_URL; @@ -26,13 +26,14 @@ public class BandcampRadioInfoItemExtractor implements StreamInfoItemExtractor { show = radioShow; } + @Nonnull @Override - public long getDuration() { + public Duration getDurationObject() { /* Duration is only present in the more detailed information that has to be queried separately. Therefore, over 300 queries would be needed every time the kiosk is opened if we were to display the real value. */ - //return query(show.getInt("id")).getLong("audio_duration"); - return 0; + //return Duration.ofSeconds(query(show.getInt("id")).getLong("audio_duration")); + return Duration.ZERO; } @Nullable diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampDiscographStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampDiscographStreamInfoItemExtractor.java index cea350460..dd21472ea 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampDiscographStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampDiscographStreamInfoItemExtractor.java @@ -43,9 +43,4 @@ public class BandcampDiscographStreamInfoItemExtractor extends BandcampStreamInf public List getThumbnails() throws ParsingException { return getImagesFromImageId(discograph.getLong("art_id"), true); } - - @Override - public long getDuration() { - return -1; - } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampPlaylistStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampPlaylistStreamInfoItemExtractor.java index 5c37ec457..ce6d19fa3 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampPlaylistStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampPlaylistStreamInfoItemExtractor.java @@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamExtractor; import javax.annotation.Nonnull; import java.io.IOException; +import java.time.Duration; import java.util.Collections; import java.util.List; @@ -46,9 +47,10 @@ public class BandcampPlaylistStreamInfoItemExtractor extends BandcampStreamInfoI return getUploaderUrl() + track.getString("title_link"); } + @Nonnull @Override - public long getDuration() { - return track.getLong("duration"); + public Duration getDurationObject() { + return Duration.ofSeconds(track.getLong("duration")); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampSearchStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampSearchStreamInfoItemExtractor.java index 18c0c0dcc..df3de4db8 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampSearchStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampSearchStreamInfoItemExtractor.java @@ -47,9 +47,4 @@ public class BandcampSearchStreamInfoItemExtractor extends BandcampStreamInfoIte public List getThumbnails() throws ParsingException { return getImagesFromSearchResult(searchResult); } - - @Override - public long getDuration() { - return -1; - } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java index f6c5ac862..79ffa82b0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java @@ -60,11 +60,6 @@ public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor return false; } - @Override - public long getDuration() throws ParsingException { - return 0; - } - @Override public long getViewCount() throws ParsingException { return -1; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKiosk.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKiosk.java index d38d65fd5..516ea96c7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKiosk.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKiosk.java @@ -64,7 +64,7 @@ public class MediaCCCRecentKiosk extends KioskExtractor { .map(JsonObject.class::cast) .map(MediaCCCRecentKioskExtractor::new) // #813 / voc/voctoweb#609 -> returns faulty data -> filter it out - .filter(extractor -> extractor.getDuration() > 0) + .filter(extractor -> !extractor.getDurationObject().isZero()) .forEach(collector::commit); return new InfoItemsPage<>(collector, null); diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java index df25b28d8..ace06614b 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java @@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConfe import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; +import java.time.Duration; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.List; @@ -53,10 +54,11 @@ public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor { } @Override - public long getDuration() { + @Nonnull + public Duration getDurationObject() { // duration and length have the same value, see // https://github.com/voc/voctoweb/blob/master/app/views/public/shared/_event.json.jbuilder - return event.getInt("duration"); + return Duration.ofSeconds(event.getLong("duration")); } @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 ec9d00f3a..288c4fdfc 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 @@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.stream.StreamType; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.time.Duration; import java.util.List; import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromStreamItem; @@ -32,8 +33,9 @@ public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor } @Override - public long getDuration() { - return event.getInt("length"); + @Nonnull + public Duration getDurationObject() { + return Duration.ofSeconds(event.getLong("length")); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamInfoItemExtractor.java index 46aae43cc..804b9a932 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamInfoItemExtractor.java @@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.utils.JsonUtils; import javax.annotation.Nonnull; +import java.time.Duration; import java.util.List; import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getAvatarsFromOwnerAccountOrVideoChannelObject; @@ -100,8 +101,9 @@ public class PeertubeStreamInfoItemExtractor implements StreamInfoItemExtractor } @Override - public long getDuration() { - return item.getLong("duration"); + @Nonnull + public Duration getDurationObject() { + return Duration.ofSeconds(item.getLong("duration")); } protected void setBaseUrl(final String baseUrl) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudStreamInfoItemExtractor.java index 6fd6232e9..1437527b0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudStreamInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudStreamInfoItemExtractor.java @@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor; import org.schabi.newpipe.extractor.stream.StreamType; import javax.annotation.Nonnull; +import java.time.Duration; import java.util.List; import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.getAllImagesFromArtworkOrAvatarUrl; @@ -35,8 +36,9 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto } @Override - public long getDuration() { - return itemObject.getLong("duration") / 1000L; + @Nonnull + public Duration getDurationObject() { + return Duration.ofMillis(itemObject.getLong("duration")); } @Override diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java index 3579c765b..fef7119b7 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java @@ -32,8 +32,8 @@ import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; import com.grack.nanojson.JsonWriter; - import org.jsoup.nodes.Entities; + import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.Image.ResolutionLevel; import org.schabi.newpipe.extractor.downloader.Response; @@ -56,10 +56,12 @@ import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -310,21 +312,22 @@ public final class YoutubeParsingHelper { * @return the duration in seconds * @throws ParsingException when more than 3 separators are found */ - public static int parseDurationString(@Nonnull final String input) - throws ParsingException, NumberFormatException { + public static Duration parseDurationString(@Nonnull final String input) + throws ParsingException { // If time separator : is not detected, try . instead final String[] splitInput = input.contains(":") ? input.split(":") : input.split("\\."); - final int[] units = {24, 60, 60, 1}; - final int offset = units.length - splitInput.length; + final var units = List.of(ChronoUnit.DAYS, ChronoUnit.HOURS, ChronoUnit.MINUTES, + ChronoUnit.SECONDS); + final int offset = units.size() - splitInput.length; if (offset < 0) { throw new ParsingException("Error duration string with unknown format: " + input); } - int duration = 0; + Duration duration = Duration.ZERO; for (int i = 0; i < splitInput.length; i++) { - duration = units[i + offset] * (duration + convertDurationToInt(splitInput[i])); + duration = duration.plus(convertDurationToInt(splitInput[i]), units.get(i + offset)); } return duration; } @@ -341,11 +344,7 @@ public final class YoutubeParsingHelper { * @return The converted integer or 0 if the conversion failed. */ private static int convertDurationToInt(final String input) { - if (input == null || input.isEmpty()) { - return 0; - } - - final String clearedInput = Utils.removeNonDigitCharacters(input); + final String clearedInput = input != null ? Utils.removeNonDigitCharacters(input) : ""; try { return Integer.parseInt(clearedInput); } catch (final NumberFormatException ex) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java index d917eb2d7..534296589 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedInfoItemExtractor.java @@ -33,12 +33,6 @@ public class YoutubeFeedInfoItemExtractor implements StreamInfoItemExtractor { return false; } - @Override - public long getDuration() { - // Not available when fetching through the feed endpoint. - return -1; - } - @Override public long getViewCount() { return Long.parseLong(entryElement.getElementsByTag("media:statistics").first() diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMusicSongOrVideoInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMusicSongOrVideoInfoItemExtractor.java index 11b220288..8e09e1f8a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMusicSongOrVideoInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMusicSongOrVideoInfoItemExtractor.java @@ -12,6 +12,7 @@ import org.schabi.newpipe.extractor.utils.Parser; import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; +import java.time.Duration; import java.util.List; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; @@ -67,7 +68,8 @@ public class YoutubeMusicSongOrVideoInfoItemExtractor implements StreamInfoItemE } @Override - public long getDuration() throws ParsingException { + @Nonnull + public Duration getDurationObject() throws ParsingException { final String duration = descriptionElements.getObject(descriptionElements.size() - 1) .getString("text"); if (!isNullOrEmpty(duration)) { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java index 3b9326247..2b63b70ea 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeReelInfoItemExtractor.java @@ -5,7 +5,6 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import com.grack.nanojson.JsonObject; - import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.localization.DateWrapper; @@ -90,11 +89,6 @@ public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor { return false; } - @Override - public long getDuration() throws ParsingException { - return -1; - } - @Override public String getUploaderName() throws ParsingException { return null; 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 d00cee987..0a66bd073 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 @@ -41,7 +41,7 @@ import org.schabi.newpipe.extractor.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; - +import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -136,10 +136,11 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { throw new ParsingException("Could not get name"); } + @Nonnull @Override - public long getDuration() throws ParsingException { + public Duration getDurationObject() throws ParsingException { if (getStreamType() == StreamType.LIVE_STREAM) { - return -1; + return Duration.ZERO; } String duration = getTextFromObject(videoInfo.getObject("lengthText")); @@ -169,7 +170,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { if (isPremiere()) { // Premieres can be livestreams, so the duration is not available in this // case - return -1; + return Duration.ZERO; } throw new ParsingException("Could not get duration"); 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 6996111ff..e193d13fa 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 @@ -26,6 +26,7 @@ import org.schabi.newpipe.extractor.localization.DateWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.time.Duration; import java.util.List; /** @@ -40,7 +41,8 @@ public class StreamInfoItem extends InfoItem { @Nullable private DateWrapper uploadDate; private long viewCount = -1; - private long duration = -1; + @Nonnull + private Duration duration = Duration.ZERO; private String uploaderUrl = null; @Nonnull @@ -76,12 +78,21 @@ public class StreamInfoItem extends InfoItem { this.viewCount = viewCount; } - public long getDuration() { + @Nonnull + public Duration getDurationObject() { return duration; } + public void setDurationObject(@Nonnull final Duration durationObject) { + this.duration = durationObject; + } + + public long getDuration() { + return duration.toSeconds(); + } + public void setDuration(final long duration) { - this.duration = duration; + this.duration = Duration.ofSeconds(duration); } public String getUploaderUrl() { 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 399ecfe13..9b0e56d30 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 @@ -27,6 +27,7 @@ import org.schabi.newpipe.extractor.localization.DateWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.time.Duration; import java.util.List; public interface StreamInfoItemExtractor extends InfoItemExtractor { @@ -48,12 +49,25 @@ public interface StreamInfoItemExtractor extends InfoItemExtractor { boolean isAd() throws ParsingException; /** - * Get the stream duration in seconds + * Get the stream duration as a {@link Duration}. * - * @return the stream duration in seconds or -1 if no duration is available + * @return the stream duration in seconds or {@link Duration#ZERO} if no duration is available * @throws ParsingException if there is an error in the extraction */ - long getDuration() throws ParsingException; + @Nonnull + default Duration getDurationObject() throws ParsingException { + return Duration.ZERO; + } + + /** + * Get the stream duration in seconds. + * + * @return the stream duration in seconds or 0 if no duration is available + * @throws ParsingException if there is an error in the extraction + */ + default long getDuration() throws ParsingException { + return getDurationObject().toSeconds(); + } /** * Parses the number of views 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 19cd2baa8..fd132265c 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 @@ -44,12 +44,12 @@ public class StreamInfoItemsCollector throw new FoundAdException("Found ad"); } - final StreamInfoItem resultItem = new StreamInfoItem( - getServiceId(), extractor.getUrl(), extractor.getName(), extractor.getStreamType()); + final var resultItem = new StreamInfoItem(getServiceId(), extractor.getUrl(), + extractor.getName(), extractor.getStreamType()); // optional information try { - resultItem.setDuration(extractor.getDuration()); + resultItem.setDurationObject(extractor.getDurationObject()); } catch (final Exception e) { addError(e); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/ExtractorAsserts.java b/extractor/src/test/java/org/schabi/newpipe/extractor/ExtractorAsserts.java index e5bed1d69..3402ef006 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/ExtractorAsserts.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/ExtractorAsserts.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -99,12 +100,9 @@ public class ExtractorAsserts { assertGreater(expected, actual, actual + " is not > " + expected); } - public static void assertGreater( - final long expected, - final long actual, - final String message - ) { - assertTrue(actual > expected, message); + public static > void assertGreater(final T expected, final T actual, + final String message) { + assertTrue(actual.compareTo(expected) > 0, message); } public static void assertGreaterOrEqual(final long expected, final long actual) { diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCRecentListExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCRecentListExtractorTest.java index 6915859cd..4527dd891 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCRecentListExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/media_ccc/MediaCCCRecentListExtractorTest.java @@ -14,6 +14,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.kiosk.KioskExtractor; import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import java.time.Duration; import java.util.List; import java.util.stream.Stream; @@ -41,9 +42,9 @@ public class MediaCCCRecentListExtractorTest { isNullOrEmpty(item.getName()), "Name=[" + item.getName() + "] of " + item + " is empty or null" ), - () -> assertGreater(0, - item.getDuration(), - "Duration[=" + item.getDuration() + "] of " + item + " is <= 0" + () -> assertGreater(Duration.ZERO, + item.getDurationObject(), + "Duration[=" + item.getDurationObject() + "] of " + item + " is <= 0" ) ); } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelperTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelperTest.java index dc7733344..bdb848d82 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelperTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelperTest.java @@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.stream.AudioTrackType; import java.io.IOException; +import java.time.Duration; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -38,9 +39,12 @@ public class YoutubeParsingHelperTest { @Test void testParseDurationString() throws ParsingException { - assertEquals(1162567, YoutubeParsingHelper.parseDurationString("12:34:56:07")); - assertEquals(4445767, YoutubeParsingHelper.parseDurationString("1,234:56:07")); - assertEquals(754, YoutubeParsingHelper.parseDurationString("12:34 ")); + assertEquals(Duration.ofDays(12).plusHours(34).plusMinutes(56).plusSeconds(7), + YoutubeParsingHelper.parseDurationString("12:34:56:07")); + assertEquals(Duration.ofHours(1234).plusMinutes(56).plusSeconds(7), + YoutubeParsingHelper.parseDurationString("1,234:56:07")); + assertEquals(Duration.ofMinutes(12).plusSeconds(34), + YoutubeParsingHelper.parseDurationString("12:34 ")); } @Test