Skip to content

Commit 5c3115b

Browse files
Obtain stream length as a Duration
1 parent 7c7ceac commit 5c3115b

21 files changed

+177
-149
lines changed

extractor/src/main/java/org/schabi/newpipe/extractor/localization/TimeAgoParser.java

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import org.schabi.newpipe.extractor.timeago.PatternsHolder;
55
import org.schabi.newpipe.extractor.utils.Parser;
66

7+
import java.time.Duration;
78
import java.time.OffsetDateTime;
89
import java.time.ZoneOffset;
910
import java.time.temporal.ChronoUnit;
1011
import java.util.ArrayList;
1112
import java.util.List;
1213
import java.util.Map;
13-
import java.util.regex.Pattern;
14-
import java.util.regex.Matcher;
1514
import java.util.regex.MatchResult;
15+
import java.util.regex.Pattern;
1616

1717
/**
1818
* A helper class that is meant to be used by services that need to parse durations such as
@@ -68,45 +68,40 @@ public DateWrapper parse(final String textualDate) throws ParsingException {
6868
}
6969

7070
/**
71-
* Parses a textual duration into a duration computer number.
71+
* Parses a textual duration into a {@link Duration} object.
7272
*
7373
* @param textualDuration the textual duration to parse
74-
* @return the textual duration parsed, as a primitive {@code long}
75-
* @throws ParsingException if the textual duration could not be parsed
74+
* @return the textual duration parsed as a {@link Duration}
7675
*/
77-
public long parseDuration(final String textualDuration) throws ParsingException {
76+
public Duration parseDuration(final String textualDuration) throws ParsingException {
7877
// We can't use Matcher.results, as it is only available on Android 14 and above
79-
final Matcher matcher = DURATION_PATTERN.matcher(textualDuration);
78+
final var matcher = DURATION_PATTERN.matcher(textualDuration);
8079
final List<MatchResult> results = new ArrayList<>();
8180
while (matcher.find()) {
8281
results.add(matcher.toMatchResult());
8382
}
8483

85-
return results.stream()
86-
.map(match -> {
87-
final String digits = match.group(1);
88-
final String word = match.group(2);
89-
90-
int amount;
91-
try {
92-
amount = Integer.parseInt(digits);
93-
} catch (final NumberFormatException ignored) {
94-
amount = 1;
95-
}
96-
97-
final ChronoUnit unit;
98-
try {
99-
unit = parseChronoUnit(word);
100-
} catch (final ParsingException ignored) {
101-
return 0L;
102-
}
103-
104-
return amount * unit.getDuration().getSeconds();
105-
})
106-
.filter(n -> n > 0)
107-
.reduce(Long::sum)
108-
.orElseThrow(() -> new ParsingException(
109-
"Could not parse duration \"" + textualDuration + "\""));
84+
var duration = Duration.ZERO;
85+
for (final var match : results) {
86+
final String digits = match.group(1);
87+
final String word = match.group(2);
88+
89+
long amount;
90+
try {
91+
amount = Long.parseLong(digits);
92+
} catch (final NumberFormatException ignored) {
93+
amount = 1;
94+
}
95+
96+
try {
97+
duration = duration.plus(amount, parseChronoUnit(word));
98+
} catch (final ParsingException ignored) {
99+
}
100+
}
101+
if (duration.isZero()) {
102+
throw new ParsingException("Could not parse duration \"" + textualDuration + "\"");
103+
}
104+
return duration;
110105
}
111106

112107
private int parseTimeAgoAmount(final String textualDate) {

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampRadioInfoItemExtractor.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22

33
package org.schabi.newpipe.extractor.services.bandcamp.extractors;
44

5+
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.BASE_URL;
6+
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromImageId;
7+
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.parseDate;
8+
59
import com.grack.nanojson.JsonObject;
10+
611
import org.schabi.newpipe.extractor.Image;
712
import org.schabi.newpipe.extractor.exceptions.ParsingException;
813
import org.schabi.newpipe.extractor.localization.DateWrapper;
914
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
1015
import org.schabi.newpipe.extractor.stream.StreamType;
1116

12-
import javax.annotation.Nonnull;
13-
import javax.annotation.Nullable;
14-
17+
import java.time.Duration;
1518
import java.util.List;
1619

17-
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.BASE_URL;
18-
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromImageId;
19-
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.parseDate;
20+
import javax.annotation.Nonnull;
21+
import javax.annotation.Nullable;
2022

2123
public class BandcampRadioInfoItemExtractor implements StreamInfoItemExtractor {
2224

@@ -26,13 +28,14 @@ public BandcampRadioInfoItemExtractor(final JsonObject radioShow) {
2628
show = radioShow;
2729
}
2830

31+
@Nonnull
2932
@Override
30-
public long getDuration() {
33+
public Duration getDuration() {
3134
/* Duration is only present in the more detailed information that has to be queried
3235
separately. Therefore, over 300 queries would be needed every time the kiosk is opened if we
3336
were to display the real value. */
3437
//return query(show.getInt("id")).getLong("audio_duration");
35-
return 0;
38+
return Duration.ZERO;
3639
}
3740

3841
@Nullable

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampDiscographStreamInfoItemExtractor.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem;
22

3+
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromImageId;
4+
35
import com.grack.nanojson.JsonObject;
6+
47
import org.schabi.newpipe.extractor.Image;
58
import org.schabi.newpipe.extractor.exceptions.ParsingException;
69
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper;
710

8-
import javax.annotation.Nonnull;
911
import java.util.List;
1012

11-
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromImageId;
13+
import javax.annotation.Nonnull;
1214

1315
public class BandcampDiscographStreamInfoItemExtractor extends BandcampStreamInfoItemExtractor {
1416

@@ -43,9 +45,4 @@ public String getUrl() throws ParsingException {
4345
public List<Image> getThumbnails() throws ParsingException {
4446
return getImagesFromImageId(discograph.getLong("art_id"), true);
4547
}
46-
47-
@Override
48-
public long getDuration() {
49-
return -1;
50-
}
5148
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampPlaylistStreamInfoItemExtractor.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33
package org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem;
44

55
import com.grack.nanojson.JsonObject;
6+
67
import org.schabi.newpipe.extractor.Image;
78
import org.schabi.newpipe.extractor.StreamingService;
89
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
910
import org.schabi.newpipe.extractor.exceptions.ParsingException;
1011
import org.schabi.newpipe.extractor.stream.StreamExtractor;
1112

12-
import javax.annotation.Nonnull;
1313
import java.io.IOException;
14+
import java.time.Duration;
1415
import java.util.Collections;
1516
import java.util.List;
1617

18+
import javax.annotation.Nonnull;
19+
1720
public class BandcampPlaylistStreamInfoItemExtractor extends BandcampStreamInfoItemExtractor {
1821

1922
private final JsonObject track;
@@ -46,9 +49,10 @@ public String getUrl() {
4649
return getUploaderUrl() + track.getString("title_link");
4750
}
4851

52+
@Nonnull
4953
@Override
50-
public long getDuration() {
51-
return track.getLong("duration");
54+
public Duration getDuration() {
55+
return Duration.ofSeconds(track.getLong("duration"));
5256
}
5357

5458
@Override

extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/extractors/streaminfoitem/BandcampSearchStreamInfoItemExtractor.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem;
22

3+
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromSearchResult;
4+
35
import org.jsoup.nodes.Element;
46
import org.schabi.newpipe.extractor.Image;
57
import org.schabi.newpipe.extractor.exceptions.ParsingException;
68

7-
import javax.annotation.Nonnull;
89
import java.util.List;
910

10-
import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampExtractorHelper.getImagesFromSearchResult;
11+
import javax.annotation.Nonnull;
1112

1213
public class BandcampSearchStreamInfoItemExtractor extends BandcampStreamInfoItemExtractor {
1314

@@ -47,9 +48,4 @@ public String getUrl() throws ParsingException {
4748
public List<Image> getThumbnails() throws ParsingException {
4849
return getImagesFromSearchResult(searchResult);
4950
}
50-
51-
@Override
52-
public long getDuration() {
53-
return -1;
54-
}
5551
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCLiveStreamKioskExtractor.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
22

3+
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromLiveStreamItem;
4+
35
import com.grack.nanojson.JsonObject;
6+
47
import org.schabi.newpipe.extractor.Image;
58
import org.schabi.newpipe.extractor.exceptions.ParsingException;
69
import org.schabi.newpipe.extractor.localization.DateWrapper;
710
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
811
import org.schabi.newpipe.extractor.stream.StreamType;
912

10-
import javax.annotation.Nonnull;
11-
import javax.annotation.Nullable;
1213
import java.util.List;
1314

14-
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromLiveStreamItem;
15+
import javax.annotation.Nonnull;
16+
import javax.annotation.Nullable;
1517

1618
public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor {
1719

@@ -60,11 +62,6 @@ public boolean isAd() throws ParsingException {
6062
return false;
6163
}
6264

63-
@Override
64-
public long getDuration() throws ParsingException {
65-
return 0;
66-
}
67-
6865
@Override
6966
public long getViewCount() throws ParsingException {
7067
return -1;

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKiosk.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
1818

1919
import java.io.IOException;
20+
import java.time.Duration;
2021
import java.util.Comparator;
2122

2223
import javax.annotation.Nonnull;
@@ -64,7 +65,7 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, Extrac
6465
.map(JsonObject.class::cast)
6566
.map(MediaCCCRecentKioskExtractor::new)
6667
// #813 / voc/voctoweb#609 -> returns faulty data -> filter it out
67-
.filter(extractor -> extractor.getDuration() > 0)
68+
.filter(extractor -> extractor.getDuration().compareTo(Duration.ZERO) > 0)
6869
.forEach(collector::commit);
6970

7071
return new InfoItemsPage<>(collector, null);

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCRecentKioskExtractor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
1010
import org.schabi.newpipe.extractor.stream.StreamType;
1111

12+
import java.time.Duration;
1213
import java.time.ZonedDateTime;
1314
import java.time.format.DateTimeFormatter;
1415
import java.util.List;
@@ -52,11 +53,12 @@ public boolean isAd() {
5253
return false;
5354
}
5455

56+
@Nonnull
5557
@Override
56-
public long getDuration() {
58+
public Duration getDuration() {
5759
// duration and length have the same value, see
5860
// https://github.com/voc/voctoweb/blob/master/app/views/public/shared/_event.json.jbuilder
59-
return event.getInt("duration");
61+
return Duration.ofSeconds(event.getLong("duration"));
6062
}
6163

6264
@Override

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/infoItems/MediaCCCStreamInfoItemExtractor.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems;
22

3+
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromStreamItem;
4+
35
import com.grack.nanojson.JsonObject;
6+
47
import org.schabi.newpipe.extractor.Image;
58
import org.schabi.newpipe.extractor.exceptions.ParsingException;
69
import org.schabi.newpipe.extractor.localization.DateWrapper;
710
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper;
811
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
912
import org.schabi.newpipe.extractor.stream.StreamType;
1013

11-
import javax.annotation.Nonnull;
12-
import javax.annotation.Nullable;
14+
import java.time.Duration;
1315
import java.util.List;
1416

15-
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromStreamItem;
17+
import javax.annotation.Nonnull;
18+
import javax.annotation.Nullable;
1619

1720
public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor {
1821
private final JsonObject event;
@@ -31,9 +34,10 @@ public boolean isAd() {
3134
return false;
3235
}
3336

37+
@Nonnull
3438
@Override
35-
public long getDuration() {
36-
return event.getInt("length");
39+
public Duration getDuration() {
40+
return Duration.ofSeconds(event.getInt("length"));
3741
}
3842

3943
@Override

extractor/src/main/java/org/schabi/newpipe/extractor/services/peertube/extractors/PeertubeStreamInfoItemExtractor.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package org.schabi.newpipe.extractor.services.peertube.extractors;
22

3+
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getAvatarsFromOwnerAccountOrVideoChannelObject;
4+
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getThumbnailsFromPlaylistOrVideoItem;
5+
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.parseDateFrom;
6+
37
import com.grack.nanojson.JsonObject;
8+
49
import org.schabi.newpipe.extractor.Image;
510
import org.schabi.newpipe.extractor.ServiceList;
611
import org.schabi.newpipe.extractor.exceptions.ParsingException;
@@ -9,12 +14,10 @@
914
import org.schabi.newpipe.extractor.stream.StreamType;
1015
import org.schabi.newpipe.extractor.utils.JsonUtils;
1116

12-
import javax.annotation.Nonnull;
17+
import java.time.Duration;
1318
import java.util.List;
1419

15-
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getAvatarsFromOwnerAccountOrVideoChannelObject;
16-
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.getThumbnailsFromPlaylistOrVideoItem;
17-
import static org.schabi.newpipe.extractor.services.peertube.PeertubeParsingHelper.parseDateFrom;
20+
import javax.annotation.Nonnull;
1821

1922
public class PeertubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
2023

@@ -99,9 +102,10 @@ public StreamType getStreamType() {
99102
return item.getBoolean("isLive") ? StreamType.LIVE_STREAM : StreamType.VIDEO_STREAM;
100103
}
101104

105+
@Nonnull
102106
@Override
103-
public long getDuration() {
104-
return item.getLong("duration");
107+
public Duration getDuration() {
108+
return Duration.ofSeconds(item.getLong("duration"));
105109
}
106110

107111
protected void setBaseUrl(final String baseUrl) {

0 commit comments

Comments
 (0)