Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/tunein.py (Python)

Code before:
            contents = self._call_api(
                podcast_id, 'contents',
                f'Downloading page {page + 1}', query={
                    'filter': 't:free',
                    'limit': self._PAGE_SIZE,
                    'offset': page * self._PAGE_SIZE,
                })

            yield from traverse_obj(contents, (
                'Items', ..., 'GuideId', {str}, filter, all, filter))

            if not traverse_obj(contents, ('Paging', 'Next', {url_or_none})):
                break

    def _real_extract(self, url):
        podcast_id = self._match_id(url)

        return self.playlist_from_matches(
            self._entries(podcast_id), podcast_id,
            traverse_obj(self._call_api(podcast_id), ('Item', 'Title', {str})),
            getter=lambda x: update_url_query(url, {'topicId': x[1:]}))


class TuneInPodcastEpisodeIE(TuneInBaseIE):
    IE_NAME = 'tunein:podcast'
    _VALID_URL = r'https?://tunein\.com/podcasts(?:/[^/?#]+)?/[^/?#]+(?P<series_id>p\d+)/?\?[^#]*?(?<=\?|&)(?i:\btopicid)=(?P<id>\d+)(?:[&#]|$)'
    _TESTS = [{
        'url': 'https://tunein.com/podcasts/Technology-Podcasts/Artificial-Intelligence-p1153019/?topicId=236404354',
        'info_dict': {
            'id': 't236404354',
            'ext': 'mp3',
            'title': '#351 – MrBeast: Future of YouTube, Twitter, TikTok, and Instagram',
            'alt_title': 'Technology Podcasts >',
            'cast': 'count:1',
            'description': 'md5:1029895354ef073ff00f20b82eb6eb71',
            'display_id': '236404354',
            'duration': 8330,
            'thumbnail': r're:https?://.+',
            'timestamp': 1673458571,
            'upload_date': '20230111',
            'series': 'Lex Fridman Podcast',
            'series_id': 'p1153019',
        },
    }, {
        'url': 'https://tunein.com/podcasts/The-BOB--TOM-Show-Free-Podcast-p20069/?topicId=174556405',
        'info_dict': {
            'id': 't174556405',
            'ext': 'mp3',
            'title': 'B&T Extra: Ohhh Yeah, It\'s Sexy Time',
            'alt_title': 'Westwood One >',
            'cast': 'count:2',

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://tunein\.com/podcasts(?:/[^/?#]+){1,2}(?P<series_id>p\d+)/?\?(?:[^#]+&)?(?i:topicid)=(?P<id>\d+)'
```

Code after:
    def suitable(cls, url):
        return False if TuneInPodcastEpisodeIE.suitable(url) else super().suitable(url)

    def _fetch_page(self, url, podcast_id, page=0):
        items = self._call_api(
            podcast_id, 'contents', f'Downloading page {page + 1}', query={
                'filter': 't:free',
                'limit': self._PAGE_SIZE,
                'offset': page * self._PAGE_SIZE,
            },
        )['Items']

        for item in traverse_obj(items, (..., 'GuideId', {str}, filter)):
            yield self.url_result(update_url_query(url, {'topicId': item[1:]}))

    def _real_extract(self, url):
        podcast_id = self._match_id(url)

        return self.playlist_result(OnDemandPagedList(
            functools.partial(self._fetch_page, url, podcast_id), self._PAGE_SIZE),
            podcast_id, traverse_obj(self._call_api(podcast_id), ('Item', 'Title', {str})))


class TuneInPodcastEpisodeIE(TuneInBaseIE):
    IE_NAME = 'tunein:podcast'
    _VALID_URL = r'https?://tunein\.com/podcasts(?:/[^/?#]+){1,2}(?P<series_id>p\d+)/?\?(?:[^#]+&)?(?i:topicid)=(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://tunein.com/podcasts/Technology-Podcasts/Artificial-Intelligence-p1153019/?topicId=236404354',
        'info_dict': {
            'id': 't236404354',
            'ext': 'mp3',
            'title': '#351 – MrBeast: Future of YouTube, Twitter, TikTok, and Instagram',
            'alt_title': 'Technology Podcasts >',
            'cast': 'count:1',
            'description': 'md5:1029895354ef073ff00f20b82eb6eb71',
            'display_id': '236404354',
            'duration': 8330,
            'thumbnail': r're:https?://.+',
            'timestamp': 1673458571,
            'upload_date': '20230111',
            'series': 'Lex Fridman Podcast',
            'series_id': 'p1153019',
        },
    }, {
        'url': 'https://tunein.com/podcasts/The-BOB--TOM-Show-Free-Podcast-p20069/?topicId=174556405',
        'info_dict': {
            'id': 't174556405',
            'ext': 'mp3',
            'title': 'B&T Extra: Ohhh Yeah, It\'s Sexy Time',
            'alt_title': 'Westwood One >',
            'cast': 'count:2',