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

Code before:
        },
        'skip': 'Invalid URL',
    }]

    def _real_extract(self, url):
        channel_id = self._match_id(url)
        media_id = self._extract_url_media_id(url)
        if not self._yes_playlist(channel_id, media_id, playlist_label='channel'):
            return self.url_result(f'wistia:{media_id}', 'Wistia')

        try:
            data = self._download_embed_config('channel', channel_id, url)
        except (ExtractorError, HTTPError):
            # Some channels give a 403 from the JSON API
            self.report_warning('Failed to download channel data from API, falling back to webpage.')
            webpage = self._download_webpage(f'https://fast.wistia.net/embed/channel/{channel_id}', channel_id)
            data = self._parse_json(
                self._search_regex(rf'wchanneljsonp-{channel_id}\'\]\s*=[^\"]*\"([A-Za-z0-9=/]*)', webpage, 'jsonp', channel_id),
                channel_id, transform_source=lambda x: urllib.parse.unquote_plus(base64.b64decode(x).decode('utf-8')))

        # XXX: can there be more than one series?
        series = traverse_obj(data, ('series', 0), default={})

        entries = [
            self.url_result(f'wistia:{video["hashedId"]}', WistiaIE, title=video.get('name'))
            for video in traverse_obj(series, ('sections', ..., 'episodes', ...)) or []
            if video.get('hashedId')
        ]

        return self.playlist_result(
            entries, channel_id, playlist_title=series.get('title'), playlist_description=series.get('description'))

    @classmethod
    def _extract_embed_urls(cls, url, webpage):
        yield from super()._extract_embed_urls(url, webpage)
        for match in cls._extract_wistia_async_embed(webpage):
            if match.group('type') == 'wistia_channel':
                # original url may contain wmediaid query param
                yield update_url_query(f'wistiachannel:{match.group("id")}', parse_qs(url))


Review comment (suggestion):
can we make this backwards compatible
```suggestion
            for video in traverse_obj(series, ('sections', ..., ('videos', 'episodes'), ...)) or []
```

Code after:
        },
        'skip': 'Invalid URL',
    }]

    def _real_extract(self, url):
        channel_id = self._match_id(url)
        media_id = self._extract_url_media_id(url)
        if not self._yes_playlist(channel_id, media_id, playlist_label='channel'):
            return self.url_result(f'wistia:{media_id}', 'Wistia')

        try:
            data = self._download_embed_config('channel', channel_id, url)
        except (ExtractorError, HTTPError):
            # Some channels give a 403 from the JSON API
            self.report_warning('Failed to download channel data from API, falling back to webpage.')
            webpage = self._download_webpage(f'https://fast.wistia.net/embed/channel/{channel_id}', channel_id)
            data = self._parse_json(
                self._search_regex(rf'wchanneljsonp-{channel_id}\'\]\s*=[^\"]*\"([A-Za-z0-9=/]*)', webpage, 'jsonp', channel_id),
                channel_id, transform_source=lambda x: urllib.parse.unquote_plus(base64.b64decode(x).decode('utf-8')))

        # XXX: can there be more than one series?
        series = traverse_obj(data, ('series', 0), default={})

        entries = [
            self.url_result(f'wistia:{video["hashedId"]}', WistiaIE, title=video.get('name'))
            for video in traverse_obj(series, ('sections', ..., ('videos', 'episodes'), lambda _, v: v['hashedId']))
        ]

        return self.playlist_result(
            entries, channel_id, playlist_title=series.get('title'), playlist_description=series.get('description'))

    @classmethod
    def _extract_embed_urls(cls, url, webpage):
        yield from super()._extract_embed_urls(url, webpage)
        for match in cls._extract_wistia_async_embed(webpage):
            if match.group('type') == 'wistia_channel':
                # original url may contain wmediaid query param
                yield update_url_query(f'wistiachannel:{match.group("id")}', parse_qs(url))