1414
1515import javax .annotation .Nonnull ;
1616import java .io .IOException ;
17+ import java .util .HashSet ;
18+ import java .util .Set ;
1719
1820import static org .schabi .newpipe .extractor .services .soundcloud .SoundcloudParsingHelper .SOUNDCLOUD_API_V2_URL ;
1921import 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