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

Code before:
                **traverse_obj(node, {
                    'author': ('user', 'displayName', {str}),
                    'author_id': ('user', 'username', {str}),
                    'timestamp': ('created', {parse_iso8601}),
                }),
            })

        return {
            'id': track_id,
            'formats': formats,
            'comments': comments,
            **traverse_obj(cloudcast, {
                'title': ('name', {str}),
                'description': ('description', {str}),
                'thumbnail': ('picture', 'url', {url_or_none}),
                'timestamp': ('publishDate', {parse_iso8601}),
                'duration': ('audioLength', {int_or_none}),
                'uploader': ('owner', 'displayName', {str}),
                'uploader_id': ('owner', 'username', {str}),
                'uploader_url': ('owner', 'url', {url_or_none}),
                'view_count': ('plays', {int_or_none}),
                'like_count': ('favorites', 'totalCount', {int_or_none}),
                'repost_count': ('reposts', 'totalCount', {int_or_none}),
                'comment_count': ('comments', 'totalCount', {int_or_none}),
                'tags': ('tags', ..., 'tag', 'name', {str}, all, filter),
                'artists': ('featuringArtistList', ..., {str}, all, filter),
            }),
        }


class MixcloudPlaylistBaseIE(MixcloudBaseIE):
    def _get_cloudcast(self, node):
        return node

    def _get_playlist_title(self, title, slug):
        return title

    def _real_extract(self, url):
        username, slug = self._match_valid_url(url).groups()
        username = urllib.parse.unquote(username)
        if not slug:
            slug = 'uploads'
        else:
            slug = urllib.parse.unquote(slug)
        playlist_id = f'{username}_{slug}'

        is_playlist_type = self._ROOT_TYPE == 'playlist'
        playlist_type = 'items' if is_playlist_type else slug
        list_filter = ''

        has_next_page = True

Review comment (suggestion):
I would also guard against empty strings since the old code would've done the same (if not for the typo)
```suggestion
                'tags': ('tags', ..., 'tag', 'name', {str}, filter, all, filter),
                'artists': ('featuringArtistList', ..., {str}, filter, all, filter),
```

Code after:
                **traverse_obj(node, {
                    'author': ('user', 'displayName', {str}),
                    'author_id': ('user', 'username', {str}),
                    'timestamp': ('created', {parse_iso8601}),
                }),
            })

        return {
            'id': track_id,
            'formats': formats,
            'comments': comments,
            **traverse_obj(cloudcast, {
                'title': ('name', {str}),
                'description': ('description', {str}),
                'thumbnail': ('picture', 'url', {url_or_none}),
                'timestamp': ('publishDate', {parse_iso8601}),
                'duration': ('audioLength', {int_or_none}),
                'uploader': ('owner', 'displayName', {str}),
                'uploader_id': ('owner', 'username', {str}),
                'uploader_url': ('owner', 'url', {url_or_none}),
                'view_count': ('plays', {int_or_none}),
                'like_count': ('favorites', 'totalCount', {int_or_none}),
                'repost_count': ('reposts', 'totalCount', {int_or_none}),
                'comment_count': ('comments', 'totalCount', {int_or_none}),
                'tags': ('tags', ..., 'tag', 'name', {str}, filter, all, filter),
                'artists': ('featuringArtistList', ..., {str}, filter, all, filter),
            }),
        }


class MixcloudPlaylistBaseIE(MixcloudBaseIE):
    def _get_cloudcast(self, node):
        return node

    def _get_playlist_title(self, title, slug):
        return title

    def _real_extract(self, url):
        username, slug = self._match_valid_url(url).groups()
        username = urllib.parse.unquote(username)
        if not slug:
            slug = 'uploads'
        else:
            slug = urllib.parse.unquote(slug)
        playlist_id = f'{username}_{slug}'

        is_playlist_type = self._ROOT_TYPE == 'playlist'
        playlist_type = 'items' if is_playlist_type else slug
        list_filter = ''

        has_next_page = True