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

Code before:
                },
                'login_data': {
                    'enabled': True,
                    'email': email,
                    'password': password,
                }
            }).encode())['user_token']

    def _perform_login(self, username, password):
        self._login(username, password)

    def _extract_video(self, video_data, series_id=None, season_id=None, season_number=None):
        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_data['stream_url'], series_id, 'mp4')

        return {
            'id': video_data['id'],
            'title': video_data.get('name'),
            'description': video_data.get('description'),
            'formats': formats,
            'subtitles': subtitles,
            'thumbnails': traverse_obj(
                video_data, ('extra_thumbs', ..., {'url': 'thumb_url', 'height': 'height', 'width': 'width'})),
            'series_id': series_id,
            'season_id': season_id,
            'season_number': season_number,
            'episode_number': video_data.get('item_order'),
            'is_live': video_data.get('entry_type') == 3,
        }

    def _extract_series_season(self, series_id, season_id, season_number):
        api_response = self._download_json(
            'https://eu-gateway.inmobly.com/feed', series_id, query={'season_id': season_id},
            headers={'Authorization': 'Bearer ' + self._USER_TOKEN})

        for episode in api_response['items']:
            yield self._extract_video(episode, series_id, season_id, season_number)

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

        if self._USER_TOKEN is None:
            self._login('guest@inmobly.com', 'Test@gus1')

        api_response = self._download_json(
            'https://eu-gateway.inmobly.com/feed', series_id, query={'include_ids': series_id},
            headers={'Authorization': 'Bearer ' + self._USER_TOKEN})['items'][0]

        if not api_response.get('seasons'):
            return self._extract_video(api_response)

        return self.playlist_result(

Review comment (suggestion):
```suggestion
            'season_number': int_or_none(season_number),
            'episode_number': int_or_none(video_data.get('item_order')),
```

Code after:
                },
                'login_data': {
                    'enabled': True,
                    'email': email,
                    'password': password,
                }
            }).encode())['user_token']

    def _extract_video(self, video_data, series_id=None, season_id=None, season_number=None):
        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_data['stream_url'], series_id, 'mp4')

        return {
            'id': video_data['id'],
            'title': video_data.get('name'),
            'description': video_data.get('description'),
            'formats': formats,
            'subtitles': subtitles,
            'thumbnails': traverse_obj(
                video_data, ('extra_thumbs', ..., {'url': 'thumb_url', 'height': 'height', 'width': 'width'})),
            'series_id': series_id,
            'season_id': season_id,
            'season_number': int_or_none(season_number),
            'episode_number': int_or_none(video_data.get('item_order')),
            'is_live': video_data.get('entry_type') == 3,
        }

    def _extract_series_seasons(self, seasons, series_id):
        for season in seasons:
            api_response = self._download_json(
                'https://eu-gateway.inmobly.com/feed', series_id, query={'season_id': season['id']},
                headers={'Authorization': f'Bearer {self._USER_TOKEN}'})

            season_number = season.get('order')
            for episode in api_response['items']:
                yield self._extract_video(episode, series_id, season['id'], season_number)

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

        if self._USER_TOKEN is None:
            self._perform_login('guest@inmobly.com', 'Test@gus1')

        api_response = self._download_json(
            'https://eu-gateway.inmobly.com/feed', series_id, query={'include_ids': series_id},
            headers={'Authorization': f'Bearer {self._USER_TOKEN}'})['items'][0]

        if not api_response.get('seasons'):
            return self._extract_video(api_response)

        return self.playlist_result(
            self._extract_series_seasons(api_response['seasons'], series_id),