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

Code before:
            'duration': 2716.333,
            'subtitles': {'eng': [{'ext': 'vtt', 'protocol': 'm3u8_native'}]},
            'thumbnail': 'https://thumbnails.cbc.ca/maven_legacy/thumbnails/481/326/thumbnail.jpeg',
            'uploader': 'CBCC-NEW',
            'chapters': 'count:5',
            'upload_date': '20230729',
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        return {
            '_type': 'url_transparent',
            'ie_key': 'ThePlatform',
            'url': smuggle_url(
                'http://link.theplatform.com/s/ExhSPC/media/guid/2655402169/%s?mbr=true&formats=MPEG4,FLV,MP3' % video_id, {
                    'force_smil_url': True
                }),
            'id': video_id,
            '_format_sort_fields': ('res', 'proto')  # Prioritize direct http formats over HLS
        }


class CBCPlayerPlaylistIE(InfoExtractor):
    IE_NAME = 'cbc.ca:player:playlist'
    _VALID_URL = r'(?:cbcplayer:|https?://(?:www\.)?cbc\.ca/(?:player/)(?!play/))(?P<id>.+)'
    _TESTS = [{
        'url': 'https://www.cbc.ca/player/news/TV%20Shows/The%20National/Latest%20Broadcast',
        'playlist_mincount': 25,
        'info_dict': {
            'id': 'news/tv shows/the national/latest broadcast',
            'ie_key': 'CBCPlayer',
        }
    }, {
        'url': 'https://www.cbc.ca/player/news/Canada/North',
        'playlist_mincount': 25,
        'info_dict': {
            'id': 'news/canada/north',
            'ie_key': 'CBCPlayer',
        }
    }]

    def _real_extract(self, url):
        # We have no other playlist id other than the URL, so use that
        playlist_id = self._match_id(url).replace('%20', ' ').lower()
        # the json info we're looking for isn't marked as such, therefore we need a bit of a workaround.
        json_content = self._parse_json(
            re.sub(
                r'^.*?{', '{',
                get_element_by_id('initialStateDom', self._download_webpage(url, playlist_id))
            )[:-1],

Review comment (suggestion):
 - `cbcplayer:` prefix should only be matched by `CBCPlayerIE`
 - `.+` is too broad, we want to exclude query and fragment, yeah?
```suggestion
    _VALID_URL = r'https?://(?:www\.)?cbc\.ca/(?:player/)(?!play/)(?P<id>[^?#]+)'
```

Code after:
            'duration': 2716.333,
            'subtitles': {'eng': [{'ext': 'vtt', 'protocol': 'm3u8_native'}]},
            'thumbnail': 'https://thumbnails.cbc.ca/maven_legacy/thumbnails/481/326/thumbnail.jpeg',
            'uploader': 'CBCC-NEW',
            'chapters': 'count:5',
            'upload_date': '20230729',
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        return {
            '_type': 'url_transparent',
            'ie_key': 'ThePlatform',
            'url': smuggle_url(
                'http://link.theplatform.com/s/ExhSPC/media/guid/2655402169/%s?mbr=true&formats=MPEG4,FLV,MP3' % video_id, {
                    'force_smil_url': True
                }),
            'id': video_id,
            '_format_sort_fields': ('res', 'proto')  # Prioritize direct http formats over HLS
        }


class CBCPlayerPlaylistIE(InfoExtractor):
    IE_NAME = 'cbc.ca:player:playlist'
    _VALID_URL = r'https?://(?:www\.)?cbc\.ca/(?:player/)(?!play/)(?P<id>[^?#]+)'
    _TESTS = [{
        'url': 'https://www.cbc.ca/player/news/TV%20Shows/The%20National/Latest%20Broadcast',
        'playlist_mincount': 25,
        'info_dict': {
            'id': 'news/tv shows/the national/latest broadcast',
        }
    }, {
        'url': 'https://www.cbc.ca/player/news/Canada/North',
        'playlist_mincount': 25,
        'info_dict': {
            'id': 'news/canada/north',
        }
    }]

    def _real_extract(self, url):
        playlist_id = urllib.parse.unquote(self._match_id(url)).lower()
        webpage = self._download_webpage(url, playlist_id)
        json_content = self._search_json(
            r'window\.__INITIAL_STATE__\s*=', webpage, 'initial state', playlist_id)

        def entries():
            for video_id in traverse_obj(json_content, (
                'video', 'clipsByCategory', lambda k, _: k.lower() == playlist_id, 'items', ..., 'id'
            )):
                yield self.url_result(f'https://www.cbc.ca/player/play/{video_id}', CBCPlayerIE)