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

Code before:
        track_info = tralbum.get('trackinfo')
        if not track_info:
            raise ExtractorError('The page doesn\'t contain any tracks')
        # Only tracks with duration info have songs
        entries = [
            self.url_result(
                urljoin(url, t['title_link']), BandcampIE.ie_key(),
                str_or_none(t.get('track_id') or t.get('id')), t.get('title'))
            for t in track_info
            if t.get('duration')]

        current = tralbum.get('current') or {}

        return {
            '_type': 'playlist',
            'uploader_id': uploader_id,
            'id': playlist_id,
            'title': current.get('title'),
            'description': current.get('about'),
            'entries': entries,
        }


class BandcampWeeklyIE(BandcampIE):  # XXX: Do not subclass from concrete IE
    IE_NAME = 'Bandcamp:weekly'
    _VALID_URL = r'https?://(?:www\.)?bandcamp\.com(?:/radio)?/?.*?([?&])show=(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://bandcamp.com/?show=224',
        'md5': '61acc9a002bed93986b91168aa3ab433',
        'info_dict': {
            'id': '224',
            'ext': 'mp3',
            'title': 'BC Weekly April 4th 2017 - Magic Moments',
            'description': 'md5:5d48150916e8e02d030623a48512c874',
            'duration': 5829.77,
            'release_date': '20170404',
            'series': 'Bandcamp Weekly',
            'episode': 'Magic Moments',
            'episode_id': '224',
        },
        'params': {
            'format': 'mp3-128',
        },
    }, {
        'url': 'https://bandcamp.com/?blah/blah@&show=228',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        show_id = self._match_id(url)
        show_data = self._download_json(

Review comment (security):
Sorry, I had a missing `=`: what I meant was `r'https?://(?:www\.)?bandcamp\.com(?:/radio)?/?\?.*?(?<=[?&])show=(?P<id>\d+)'`:
* `https?://(?:www\.)?bandcamp\.com(?:/radio)?/?\?` to match the scheme://domain possibly followed by `/radio` and then possibly by `/`, before `?` that introduces the query parameter part
* `.*?(?<=[?&])show=` to match the shortest following substring that ends with `show=` preceded by `&` or `?` (which doesn't have to be escaped inside `[]`)
* `(?P<id>\d+)` to match one or more digit-class characters. 

Code after:
        playlist_id = album_id or uploader_id
        webpage = self._download_webpage(url, playlist_id)
        tralbum = self._extract_data_attr(webpage, playlist_id)
        track_info = tralbum.get('trackinfo')
        if not track_info:
            raise ExtractorError('The page doesn\'t contain any tracks')
        # Only tracks with duration info have songs
        entries = [
            self.url_result(
                urljoin(url, t['title_link']), BandcampIE.ie_key(),
                str_or_none(t.get('track_id') or t.get('id')), t.get('title'))
            for t in track_info
            if t.get('duration')]

        current = tralbum.get('current') or {}

        return {
            '_type': 'playlist',
            'uploader_id': uploader_id,
            'id': playlist_id,
            'title': current.get('title'),
            'description': current.get('about'),
            'entries': entries,
        }


class BandcampWeeklyIE(BandcampIE):  # XXX: Do not subclass from concrete IE
    IE_NAME = 'Bandcamp:weekly'
    _VALID_URL = r'https?://(?:www\.)?bandcamp\.com/radio/?\?(?:[^#]+&)?show=(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://bandcamp.com/radio?show=224',
        'md5': '61acc9a002bed93986b91168aa3ab433',
        'info_dict': {
            'id': '224',
            'ext': 'mp3',
            'title': 'Bandcamp Weekly, 2017-04-04',
            'description': 'md5:5d48150916e8e02d030623a48512c874',
            'thumbnail': 'https://f4.bcbits.com/img/9982549_0.jpg',
            'series': 'Bandcamp Weekly',
            'episode_id': '224',
            'release_timestamp': 1491264000,
            'release_date': '20170404',
            'duration': 5829.77,
        },
        'params': {
            'format': 'mp3-128',
        },
    }, {
        'url': 'https://bandcamp.com/radio/?foo=bar&show=224',
        'only_matching': True,
    }]