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

Code before:
    def _get_api_response(self, content_id, postdata, resource_type):
        response = self._download_json(
            'https://www.freetv.com/wordpress/wp-admin/admin-ajax.php',
            content_id, data=urlencode_postdata(postdata), fatal=False,
            note='Downloading {} {} JSON'.format(content_id, resource_type))

        if response is False:
            raise ExtractorError("Couldn't get response", expected=True)

        if response.get('data') is False:
            raise ExtractorError("Response doesn't contain {} data".format(resource_type), expected=True)

        return response

    def _extract_video(self, content_id, action="olyott_video_play"):
        api_response = self._get_api_response(
            content_id, resource_type='video',
            postdata={
                'action': action,
                'contentID': content_id,
            })

        video_id = try_get(api_response, lambda x: x['data']['displayMeta']['contentID'], expected_type=str)
        title = try_get(api_response, lambda x: x['data']['displayMeta']['title'])
        description = try_get(api_response, lambda x: x['data']['displayMeta']['desc'])
        video_url = try_get(api_response, lambda x: x['data']['displayMeta']['streamURLVideo'], expected_type=str)

        ext = determine_ext(video_url)
        if ext != 'm3u8':
            raise ExtractorError('No manifest was found', video_id=video_id, expected=True)

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_url, video_id, 'mp4')
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': title,
            'description': description,
            'formats': formats,
            'subtitles': subtitles,
        }

    def _extract_series(self, display_id, season_ids, series_title, series_description,
                        action="olyott_get_dynamic_series_content"):
        entries = []
        for season_id in season_ids:
            api_response = self._get_api_response(
                season_id, resource_type='series',
                postdata={
                    'action': action,
                    'contentID': season_id,

Review comment (suggestion):
FYI, `try_get(A, lambda x: x[b][c][d])` can be written as `traverse_obj(A, (b, c, d))`. Both are fine, just letting u know since `traverse_obj` is generally easier

Code after:
    def _get_api_response(self, content_id, resource_type, postdata):
        return self._download_json(
            'https://www.freetv.com/wordpress/wp-admin/admin-ajax.php',
            content_id, data=urlencode_postdata(postdata),
            note=f'Downloading {content_id} {resource_type} JSON')['data']


class FreeTvMoviesIE(FreeTvBaseIE):
    _VALID_URL = r'https?://(?:www\.)?freetv\.com/peliculas/(?P<id>[^/]+)'
    _TESTS = [{
        'url': 'https://www.freetv.com/peliculas/atrapame-si-puedes/',
        'md5': 'dc62d5abf0514726640077cd1591aa92',
        'info_dict': {
            'id': '428021',
            'title': 'Atrápame Si Puedes',
            'description': 'md5:ca63bc00898aeb2f64ec87c6d3a5b982',
            'ext': 'mp4',
        }
    }, {
        'url': 'https://www.freetv.com/peliculas/monstruoso/',
        'md5': '509c15c68de41cb708d1f92d071f20aa',
        'info_dict': {
            'id': '377652',
            'title': 'Monstruoso',
            'description': 'md5:333fc19ee327b457b980e54a911ea4a3',
            'ext': 'mp4',
        }
    }]

    def _extract_video(self, content_id, action='olyott_video_play'):
        api_response = self._get_api_response(content_id, 'video', {
            'action': action,
            'contentID': content_id,
        })

        video_id, video_url = api_response['displayMeta']['contentID'], api_response['displayMeta']['streamURLVideo']
        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_url, video_id, 'mp4')
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': traverse_obj(api_response, ('displayMeta', 'title')),
            'description': traverse_obj(api_response, ('displayMeta', 'desc')),
            'formats': formats,
            'subtitles': subtitles,
        }

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