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

Code before:
        'info_dict': {
            'id': 'e14223c3-7871-ef11-bdfd-000d3a980db3',
            'ext': 'm4a',
            'view_count': int,
            'upload_date': '20240913',
            'uploader_id': 'phantommusicofficial',
            'timestamp': 1726194897,
            'uploader': 'Phantom',
            'comment_count': int,
            'genres': ['Progresive Rock'],
            'description': 'md5:a38cd668f7a2843295ef284114f18429',
            'duration': 225.23,
            'like_count': int,
            'title': 'Vermilion Pt. 2 (Cover)',
            'track': 'Vermilion Pt. 2 (Cover)',
            'thumbnail': 'https://bandlabimages.azureedge.net/v1.0/songs/62b10750-7aef-4f42-ad08-1af52f577e97/',
            'media_type': 'revision',
        },
    }]

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

        qs = parse_qs(url)
        revision_id = traverse_obj(qs, (('revId', 'id'), 0, any))
        if 'bandlab.com/revision/' in url:
            revision_id = display_id

        revision_data = None
        if not revision_id:
            post_data = self._call_api(
                'posts', display_id, note='Downloading post data',
                query=traverse_obj(qs, {'sharedKey': ('sharedKey', 0)}))

            revision_id = traverse_obj(post_data, (('revisionId', ('revision', 'id')), {str}, any))
            revision_data = traverse_obj(post_data, ('revision', {dict}))

            if not revision_data and not revision_id:
                post_type = post_data.get('type')
                if post_type == 'Video':
                    return self._parse_video(post_data, url=url)
                if post_type == 'Track':
                    return self._parse_track(post_data, url=url)
                raise ExtractorError('Could not extract data')

        if not revision_data:
            revision_data = self._call_api(
                'revisions', revision_id, note='Downloading revision data', query={'edit': 'false'})

        return self._parse_revision(revision_data, url=url)


Review comment (suggestion):
not sure if it would be worth it, but alternatively we could add something like a `url_type` capture group to the `_VALID_URL` patterns

Code after:
        'info_dict': {
            'id': 'e14223c3-7871-ef11-bdfd-000d3a980db3',
            'ext': 'm4a',
            'view_count': int,
            'upload_date': '20240913',
            'uploader_id': 'phantommusicofficial',
            'timestamp': 1726194897,
            'uploader': 'Phantom',
            'comment_count': int,
            'genres': ['Progresive Rock'],
            'description': 'md5:a38cd668f7a2843295ef284114f18429',
            'duration': 225.23,
            'like_count': int,
            'title': 'Vermilion Pt. 2 (Cover)',
            'track': 'Vermilion Pt. 2 (Cover)',
            'thumbnail': 'https://bandlabimages.azureedge.net/v1.0/songs/62b10750-7aef-4f42-ad08-1af52f577e97/',
            'media_type': 'revision',
        },
    }]

    def _real_extract(self, url):
        display_id, url_type = self._match_valid_url(url).group('id', 'url_type')

        qs = parse_qs(url)
        revision_id = traverse_obj(qs, (('revId', 'id'), 0, any))
        if url_type == 'revision':
            revision_id = display_id

        revision_data = None
        if not revision_id:
            post_data = self._call_api(
                'posts', display_id, note='Downloading post data',
                query=traverse_obj(qs, {'sharedKey': ('sharedKey', 0)}))

            revision_id = traverse_obj(post_data, (('revisionId', ('revision', 'id')), {str}, any))
            revision_data = traverse_obj(post_data, ('revision', {dict}))

            if not revision_data and not revision_id:
                post_type = post_data.get('type')
                if post_type == 'Video':
                    return self._parse_video(post_data, url=url)
                if post_type == 'Track':
                    return self._parse_track(post_data, url=url)
                raise ExtractorError(f'Could not extract data for post type {post_type!r}')

        if not revision_data:
            revision_data = self._call_api(
                'revisions', revision_id, note='Downloading revision data', query={'edit': 'false'})

        return self._parse_revision(revision_data, url=url)