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 5928bc3d3..977ca2dca 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 @@ -18,6 +18,8 @@ public class TimeAgoParser { private final PatternsHolder patternsHolder; private final OffsetDateTime now; + private static final Pattern DURATION_PATTERN = Pattern.compile("(?:(\\d+) )?([A-z]+)"); + /** * Creates a helper to parse upload dates in the format '2 days ago'. *

@@ -60,16 +62,29 @@ public class TimeAgoParser { return getResultFor(parseTimeAgoAmount(textualDate), parseChronoUnit(textualDate)); } - public long parseDuration(final String textualDuration) { - final int amount = parseTimeAgoAmount(textualDuration); - ChronoUnit unit; - try { - unit = parseChronoUnit(textualDuration); - } catch (final ParsingException e) { - unit = ChronoUnit.SECONDS; - } + public long parseDuration(final String textualDuration) throws ParsingException { + return DURATION_PATTERN.matcher(textualDuration).results().map(match -> { + final String digits = match.group(1); + final String word = match.group(2); - return amount * unit.getDuration().getSeconds(); + int amount; + try { + amount = Integer.parseInt(digits); + } catch (final NumberFormatException ignored) { + amount = 1; + } + + final ChronoUnit unit; + try { + unit = parseChronoUnit(word); + } catch (final ParsingException ignored) { + return (long) 0; + } + + return amount * unit.getDuration().getSeconds(); + }).filter(n -> n > 0).reduce(Long::sum).orElseThrow(() -> new ParsingException( + String.format("could not parse duration `%s`", textualDuration)) + ); } private int parseTimeAgoAmount(final String textualDate) { 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 093a2eda3..d7afcb7c3 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 @@ -123,11 +123,11 @@ public class YoutubeChannelExtractor extends ChannelExtractor { @Nonnull @Override public String getName() throws ParsingException { - final String mdName = initialData.getObject("metadata") + final String metadataName = initialData.getObject("metadata") .getObject("channelMetadataRenderer") .getString("title"); - if (!isNullOrEmpty(mdName)) { - return mdName; + if (!isNullOrEmpty(metadataName)) { + return metadataName; } return getChannelHeader().flatMap(header -> { diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java index d6fac562c..eec1d566f 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelTabExtractor.java @@ -149,12 +149,12 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor { } protected String getChannelName() { - final String mdName = initialData + final String metadataName = initialData .getObject("metadata") .getObject("channelMetadataRenderer") .getString("title"); - if (!isNullOrEmpty(mdName)) { - return mdName; + if (!isNullOrEmpty(metadataName)) { + return metadataName; } return YouTubeChannelHelper.getChannelHeader(initialData) 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 36f9fa84b..109e5b6fd 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 @@ -175,13 +175,14 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor { // Duration of short videos in channel tab // example: "simple is best - 49 seconds - play video" + // "Breakfast at Hawaiian McDonald's - 1 minute, 1 second - play video" final String accessibilityLabel = videoInfo.getObject("accessibility") .getObject("accessibilityData").getString("label"); if (accessibilityLabel == null || timeAgoParser == null) { return 0; } - final String[] labelParts = accessibilityLabel.split(" \u2013 "); + final String[] labelParts = accessibilityLabel.split(" [\u2013-] "); if (labelParts.length > 2) { final String textualDuration = labelParts[labelParts.length - 2]; diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/localization/TimeAgoParserTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/localization/TimeAgoParserTest.java new file mode 100644 index 000000000..292d0f82c --- /dev/null +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/localization/TimeAgoParserTest.java @@ -0,0 +1,31 @@ +package org.schabi.newpipe.extractor.localization; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.schabi.newpipe.extractor.exceptions.ParsingException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class TimeAgoParserTest { + private static TimeAgoParser timeAgoParser; + + @BeforeAll + static void setUp() { + timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.DEFAULT); + } + + @Test + void testGetDuration() throws ParsingException { + assertEquals(timeAgoParser.parseDuration("one second"), 1); + assertEquals(timeAgoParser.parseDuration("second"), 1); + assertEquals(timeAgoParser.parseDuration("49 seconds"), 49); + assertEquals(timeAgoParser.parseDuration("1 minute, 1 second"), 61); + } + + @Test + void testGetDurationError() { + assertThrows(ParsingException.class, () -> timeAgoParser.parseDuration("abcd")); + assertThrows(ParsingException.class, () -> timeAgoParser.parseDuration("12 abcd")); + } +}