Skip to content

Commit 97b50d7

Browse files
committed
Fix SoundCloud channel tab pagination looping on empty pages
1 parent 8dfb0d3 commit 97b50d7

1 file changed

Lines changed: 38 additions & 3 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/extractors/SoundcloudChannelTabExtractor.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import javax.annotation.Nonnull;
1616
import java.io.IOException;
17+
import java.util.HashSet;
18+
import java.util.Set;
1719

1820
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudParsingHelper.SOUNDCLOUD_API_V2_URL;
1921
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@@ -22,6 +24,8 @@ public class SoundcloudChannelTabExtractor extends ChannelTabExtractor {
2224

2325
private static final String USERS_ENDPOINT = SOUNDCLOUD_API_V2_URL + "users/";
2426

27+
private static final int MAX_EMPTY_PAGES = 5;
28+
2529
private final String userId;
2630

2731
public SoundcloudChannelTabExtractor(final StreamingService service,
@@ -70,9 +74,40 @@ public InfoItemsPage<InfoItem> getPage(final Page page)
7074
}
7175

7276
final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId());
73-
final String nextPageUrl = SoundcloudParsingHelper.getInfoItemsFromApi(
74-
collector, page.getUrl());
77+
final Set<String> visitedPages = new HashSet<>();
78+
79+
String currentPageUrl = page.getUrl();
80+
String nextPageUrl = "";
81+
int emptyPageCount = 0;
82+
83+
while (!isNullOrEmpty(currentPageUrl)) {
84+
if (!visitedPages.add(currentPageUrl)) {
85+
// Prevent infinite loops when the API points back to an already visited page.
86+
nextPageUrl = "";
87+
break;
88+
}
89+
90+
final int itemsBefore = collector.getItems().size();
91+
final String candidateNextPage = SoundcloudParsingHelper
92+
.getInfoItemsFromApi(collector, currentPageUrl);
93+
final boolean hasNewItems = collector.getItems().size() > itemsBefore;
94+
95+
if (hasNewItems) {
96+
nextPageUrl = candidateNextPage;
97+
break;
98+
}
99+
100+
emptyPageCount++;
101+
if (emptyPageCount >= MAX_EMPTY_PAGES || isNullOrEmpty(candidateNextPage)) {
102+
// Give up after too many empty responses or when SoundCloud stops providing tokens.
103+
nextPageUrl = "";
104+
break;
105+
}
106+
107+
currentPageUrl = candidateNextPage;
108+
}
75109

76-
return new InfoItemsPage<>(collector, new Page(nextPageUrl));
110+
final Page nextPage = isNullOrEmpty(nextPageUrl) ? null : new Page(nextPageUrl);
111+
return new InfoItemsPage<>(collector, nextPage);
77112
}
78113
}

0 commit comments

Comments
 (0)