+ entries = self._extract_track_entries(info['tracks'], token)
+
+ return self.playlist_result(
+ entries, str_or_none(info.get('id')), info.get('title'))
+
+
+class SoundcloudPagedPlaylistBaseIE(SoundcloudPlaylistBaseIE):
+ def _extract_playlist(self, base_url, playlist_id, playlist_title):
+ COMMON_QUERY = {
+ 'limit': 2000000000,
+ 'linked_partitioning': '1',
+ }
+
+ query = COMMON_QUERY.copy()
+ query['offset'] = 0
+
+ next_href = base_url
+
+ entries = []
+ for i in itertools.count():
+ response = self._download_json(
+ next_href, playlist_id,
+ 'Downloading track page %s' % (i + 1), query=query)
+
+ collection = response['collection']
+
+ if not isinstance(collection, list):
+ collection = []
+
+ # Empty collection may be returned, in this case we proceed
+ # straight to next_href
+
+ def resolve_entry(candidates):
+ for cand in candidates:
+ if not isinstance(cand, dict):
+ continue
+ permalink_url = url_or_none(cand.get('permalink_url'))
+ if not permalink_url:
+ continue
+ return self.url_result(
+ permalink_url,
+ SoundcloudIE.ie_key() if SoundcloudIE.suitable(permalink_url) else None,
+ str_or_none(cand.get('id')), cand.get('title'))
+
+ for e in collection:
+ entry = resolve_entry((e, e.get('track'), e.get('playlist')))
+ if entry:
+ entries.append(entry)
+
+ next_href = response.get('next_href')
+ if not next_href:
+ break
+
+ next_href = response['next_href']
+ parsed_next_href = compat_urlparse.urlparse(next_href)
+ query = compat_urlparse.parse_qs(parsed_next_href.query)
+ query.update(COMMON_QUERY)