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

Code before:

        object_type = response.get('type')
        if object_type == 'episode':
            result = self._transform_episode_response(response)

        elif object_type == 'movie':
            result = self._transform_movie_response(response)

        elif object_type == 'movie_listing':
            first_movie_id = traverse_obj(response, ('movie_listing_metadata', 'first_movie_id'))
            if not self._yes_playlist(internal_id, first_movie_id):
                return self.url_result(f'{self._BASE_URL}/{lang}watch/{first_movie_id}', CrunchyrollBetaIE, first_movie_id)

            def entries():
                movies = self._call_api(f'movie_listings/{internal_id}/movies', internal_id, lang, 'movie list')
                for movie_response in traverse_obj(movies, ('data', ...)):
                    yield self.url_result(
                        f'{self._BASE_URL}/{lang}watch/{movie_response["id"]}',
                        CrunchyrollBetaIE, **self._transform_movie_response(movie_response))

            return self.playlist_result(entries(), **self._transform_movie_response(response))

        else:
            raise ExtractorError(f'Unknown object type {object_type}')

        if traverse_obj(response, (f'{object_type}_metadata', 'is_premium_only')) and not self._IS_PREMIUM:
            message = f'This {object_type} is for premium members only'
            if self.is_logged_in:
                raise ExtractorError(message, expected=True)
            self.raise_login_required(message)

        result['formats'], result['subtitles'] = self._extract_formats(internal_id)

        result['chapters'] = self._extract_chapters(internal_id)

        def calculate_count(item):
            return parse_count(''.join((item['displayed'], item.get('unit') or '')))

        result.update(traverse_obj(response, ('rating', {
            'like_count': ('up', {calculate_count}),
            'dislike_count': ('down', {calculate_count}),
        })))

        return result

    @staticmethod
    def _transform_episode_response(data):
        metadata = traverse_obj(data, (('episode_metadata', None), {dict}), get_all=False) or {}
        return {
            'id': data['id'],
            'title': ' \u2013 '.join((

Review comment (suggestion):
I'd maybe flip this so we don't even bother with the traversal if the user's account is premium
```suggestion
        if not self._IS_PREMIUM and traverse_obj(response, (f'{object_type}_metadata', 'is_premium_only')):
```

Code after:

        object_type = response.get('type')
        if object_type == 'episode':
            result = self._transform_episode_response(response)

        elif object_type == 'movie':
            result = self._transform_movie_response(response)

        elif object_type == 'movie_listing':
            first_movie_id = traverse_obj(response, ('movie_listing_metadata', 'first_movie_id'))
            if not self._yes_playlist(internal_id, first_movie_id):
                return self.url_result(f'{self._BASE_URL}/{lang}watch/{first_movie_id}', CrunchyrollBetaIE, first_movie_id)

            def entries():
                movies = self._call_api(f'movie_listings/{internal_id}/movies', internal_id, lang, 'movie list')
                for movie_response in traverse_obj(movies, ('data', ...)):
                    yield self.url_result(
                        f'{self._BASE_URL}/{lang}watch/{movie_response["id"]}',
                        CrunchyrollBetaIE, **self._transform_movie_response(movie_response))

            return self.playlist_result(entries(), **self._transform_movie_response(response))

        else:
            raise ExtractorError(f'Unknown object type {object_type}')

        if not self._IS_PREMIUM and traverse_obj(response, (f'{object_type}_metadata', 'is_premium_only')):
            message = f'This {object_type} is for premium members only'
            if self.is_logged_in:
                raise ExtractorError(message, expected=True)
            self.raise_login_required(message)

        result['formats'], result['subtitles'] = self._extract_stream(internal_id)

        result['chapters'] = self._extract_chapters(internal_id)

        def calculate_count(item):
            return parse_count(''.join((item['displayed'], item.get('unit') or '')))

        result.update(traverse_obj(response, ('rating', {
            'like_count': ('up', {calculate_count}),
            'dislike_count': ('down', {calculate_count}),
        })))

        return result

    @staticmethod
    def _transform_episode_response(data):
        metadata = traverse_obj(data, (('episode_metadata', None), {dict}), get_all=False) or {}
        return {
            'id': data['id'],
            'title': ' \u2013 '.join((