Skip to content

Commit 7a511c8

Browse files
committed
Fixed channel and playlist pagination extraction 🥳
1 parent c25f142 commit 7a511c8

File tree

6 files changed

+59
-28
lines changed

6 files changed

+59
-28
lines changed

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/invidious/InvidiousParsingHelper.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.grack.nanojson.JsonParser;
99
import com.grack.nanojson.JsonParserException;
1010

11-
import org.schabi.newpipe.extractor.Page;
1211
import org.schabi.newpipe.extractor.downloader.Response;
1312
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
1413
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -111,10 +110,6 @@ public static String getUid(@Nonnull final String id) {
111110
return id;
112111
}
113112

114-
public static Page getPage(final String url, final int page) {
115-
return new Page(url + "?page=" + page, String.valueOf(page));
116-
}
117-
118113
/**
119114
* Get thumbnail URL at a reasonable quality
120115
*

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/invidious/extractors/InvidiousChannelExtractor.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.schabi.newpipe.extractor.downloader.Downloader;
1212
import org.schabi.newpipe.extractor.downloader.Response;
1313
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
14+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
1415
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
1516
import org.schabi.newpipe.extractor.services.youtube.invidious.InvidiousParsingHelper;
1617
import org.schabi.newpipe.extractor.services.youtube.invidious.InvidiousService;
@@ -21,7 +22,6 @@
2122

2223
import javax.annotation.Nonnull;
2324

24-
2525
public class InvidiousChannelExtractor extends ChannelExtractor {
2626

2727
private final String baseUrl;
@@ -41,31 +41,41 @@ public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, Extrac
4141
return getPage(getPage(1));
4242
}
4343

44-
protected Page getPage(final int page) {
45-
return InvidiousParsingHelper.getPage(
46-
baseUrl + "/api/v1/channels/videos/" + json.getString("authorId"),
47-
page
48-
);
44+
protected Page getPage(final int page) throws ParsingException {
45+
return new Page(
46+
baseUrl + "/api/v1/channels/videos/" + getUid(getId())
47+
+ "?page=" + page,
48+
String.valueOf(page));
4949
}
5050

5151
@Override
5252
public InfoItemsPage<StreamInfoItem> getPage(
5353
final Page page
5454
) throws IOException, ExtractionException {
55+
if (page == null) {
56+
return InfoItemsPage.emptyPage();
57+
}
58+
5559
final Response rp = NewPipe.getDownloader().get(page.getUrl());
5660
final JsonArray array =
5761
InvidiousParsingHelper.getValidJsonArrayFromResponse(rp, page.getUrl());
5862

63+
if (array.isEmpty()) {
64+
return InfoItemsPage.emptyPage();
65+
}
66+
5967
final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
6068
array.stream()
6169
.filter(JsonObject.class::isInstance)
6270
.map(JsonObject.class::cast)
6371
.map(o -> new InvidiousStreamInfoItemExtractor(o, baseUrl))
6472
.forEach(collector::commit);
6573

66-
final Page nextPage = array.size() < 59
67-
// max number of items per page
68-
// with Second it is 29 but next Page logic is not implemented
74+
// If there are less than 60 results we reached the end
75+
// CHECKSTYLE:OFF - url has to be there in one piece
76+
// https://github.com/iv-org/invidious/blob/4900ce24fac163d801a56af1fcf0f4c207448adf/src/invidious/routes/api/v1/channels.cr#L178
77+
// CHECKSTYLE:ON
78+
final Page nextPage = array.size() < 60
6979
? null
7080
: getPage(Integer.parseInt(page.getId()) + 1);
7181

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/invidious/extractors/InvidiousPlaylistExtractor.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ public InvidiousPlaylistExtractor(
3535
@Nonnull
3636
@Override
3737
public String getThumbnailUrl() {
38-
final JsonArray thumbnails = json.getArray("authorThumbnails");
39-
return InvidiousParsingHelper.getThumbnailUrl(thumbnails);
38+
return InvidiousParsingHelper.getThumbnailUrl(json.getArray("authorThumbnails"));
4039
}
4140

4241
@Override
@@ -63,14 +62,18 @@ public long getStreamCount() {
6362
@Nonnull
6463
@Override
6564
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
66-
return getPage(getPage(1));
65+
return getPage(getPageByIndex(0));
6766
}
6867

6968
@Override
7069
public InfoItemsPage<StreamInfoItem> getPage(
7170
final Page page
7271
) throws IOException, ExtractionException {
73-
if (Integer.parseInt(page.getId()) != 1) {
72+
if (page == null) {
73+
return InfoItemsPage.emptyPage();
74+
}
75+
// Initial fetched page (onFetchPage) already contains these info so don't fetch again
76+
if (Integer.parseInt(page.getId()) != 0) {
7477
final Response rp = NewPipe.getDownloader().get(page.getUrl());
7578
json = InvidiousParsingHelper.getValidJsonObjectFromResponse(rp, page.getUrl());
7679
}
@@ -84,17 +87,40 @@ public InfoItemsPage<StreamInfoItem> getPage(
8487
.map(commentObj -> new InvidiousStreamInfoItemExtractor(commentObj, baseUrl))
8588
.forEach(collector::commit);
8689

87-
final Page nextPage = videos.size() < 99
88-
// max number of items per page
89-
? null
90-
: getPage(Integer.parseInt(page.getId()) + 1);
90+
final int lastIndex = videos.isEmpty()
91+
? -1
92+
: videos.getObject(videos.size() - 1).getInt("index", -1);
9193

94+
final Page nextPage = lastIndex == -1 || lastIndex >= getStreamCount() - 1
95+
? null
96+
: getPageByIndex(lastIndex);
9297

9398
return new InfoItemsPage<>(collector, nextPage);
9499
}
95100

96-
public Page getPage(final int page) throws ParsingException {
97-
return InvidiousParsingHelper.getPage(baseUrl + "/api/v1/playlists/" + getId(), page);
101+
/*
102+
* Note: Querying is done by index and not pagination, because it's a lot easier
103+
* // CHECKSTYLE:OFF - url has to be there in one piece
104+
* https://github.com/iv-org/invidious/blob/4900ce24fac163d801a56af1fcf0f4c207448adf/src/invidious/routes/api/v1/misc.cr#L20-L22
105+
* // CHECKSTYLE:ON
106+
*
107+
* e.g. Paging contains multiple duplicate items:
108+
* Playlist-Size=505
109+
* Page StartIndex EndIndex Video-Count
110+
* 1 0 199 200
111+
* 2 50 249 200
112+
* 3 150 349 200
113+
* 4 250 449 200
114+
* 5 350 504 154
115+
* 6 450 504 54
116+
* 7 -
117+
*
118+
* Also note that the index is also used as offset
119+
*/
120+
public Page getPageByIndex(final int index) throws ParsingException {
121+
return new Page(
122+
baseUrl + "/api/v1/playlists/" + getId() + "?index=" + index,
123+
String.valueOf(index));
98124
}
99125

100126
@Override

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/invidious/linkHandler/InvidiousLinkHandlerFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public interface InvidiousLinkHandlerFactory extends YoutubeLikeLinkHandlerFacto
1313
@Override
1414
default boolean isInvidiousUrl(final URL url) {
1515
return Utils.removeMAndWWWFromHost(url.getHost())
16-
.equalsIgnoreCase(Utils.getHostOrNull(getInvidiousBaseUrl())) &&
17-
YoutubeUrlHelper.isInvidioURL(url);
16+
.equalsIgnoreCase(Utils.getHostOrNull(getInvidiousBaseUrl()))
17+
&& YoutubeUrlHelper.isInvidioURL(url);
1818
}
1919
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/shared/linkHandler/YoutubeLikeLinkHandlerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ default boolean isSupportedYouTubeLikeHost(final URL url) {
1414
|| YoutubeUrlHelper.isY2ubeURL(url);
1515
}
1616

17-
boolean isInvidiousUrl(final URL url);
17+
boolean isInvidiousUrl(URL url);
1818
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfoItemsCollector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void commit(final StreamInfoItemExtractor extractor) {
107107
try {
108108
addItem(extract(extractor));
109109
} catch (final FoundAdException ae) {
110-
//System.out.println("AD_WARNING: " + ae.getMessage());
110+
// Do nothing
111111
} catch (final Exception e) {
112112
addError(e);
113113
}

0 commit comments

Comments
 (0)