Skip to content

Commit d6165fa

Browse files
committed
Fix SoundCloud artist tracks page infinite loading
Style fix: remove trailing space at line 28 Update MAX_EMPTY_PAGES value to 3 with proper JDoc formatting Add JavaDoc for MAX_EMPTY_PAGES Rewite getPage method to internally handle emptyItems case
1 parent 8dfb0d3 commit d6165fa

1 file changed

Lines changed: 39 additions & 3 deletions

File tree

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

Lines changed: 39 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,9 @@ public class SoundcloudChannelTabExtractor extends ChannelTabExtractor {
2224

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

27+
/** Empty page cap against infinite pagination loops. */
28+
private static final int MAX_EMPTY_PAGES = 3;
29+
2530
private final String userId;
2631

2732
public SoundcloudChannelTabExtractor(final StreamingService service,
@@ -70,9 +75,40 @@ public InfoItemsPage<InfoItem> getPage(final Page page)
7075
}
7176

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

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

0 commit comments

Comments
 (0)