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

Code before:
        {
        'url': 'https://app.itpro.tv/course/beyond-tech/job-interview-tips',
        'md5': '101a299b98c47ccf4c67f9f0951defa8',
        'info_dict': {
            'id': 'job-interview-tips',
            'ext': 'mp4',
            'title': 'Job Interview Tips',
            'thumbnail': 'https://s3.amazonaws.com:443/production-itprotv-thumbnails/2f370bf5-294d-4bbe-ab80-c0b5781630ea.png',
            'description': "Did you know that preparation is one of the most important aspects of a successful job interview? Just as the interviewer will do their research on you, it's equally as important for you to do your research on the company. In this episode Jo will share with you some key preparation tips and best practices that will hopefully help you nail your next job interview!",
            'duration': 267,
            'series': 'Beyond Tech',
            'series_id': 'beyond-tech',
            'availability': 'needs_auth',
            'chapter': 'Job Development',
            'chapter_number': 2,
            'chapter_id': '5f7c78d424330c000edf04d9'
        },

    }
    ]

    def _get_course_api_json(self, webpage, course_name):
        jwt = self._fetch_jwt(webpage)

        if jwt:
            headers = {'Authorization': 'Bearer ' + jwt}
            course_api = self._download_json(
                f'https://api.itpro.tv/api/urza/v3/consumer-web/course?url={course_name}&brand=00002560-0000-3fa9-0000-1d61000035f3',
                course_name, headers=headers, note='Fetching data from course API')

        return course_api

    def _get_episode_api_json(self, webpage, episode_id):
        jwt = self._fetch_jwt(webpage)

        if jwt:
            headers = {'Authorization': 'Bearer ' + jwt}
            episode_api = self._download_json(
                f'https://api.itpro.tv/api/urza/v3/consumer-web/brand/00002560-0000-3fa9-0000-1d61000035f3/episode?url={episode_id}',
                episode_id, headers=headers, note='Fetching data from episode API')

        return episode_api

    def _fetch_jwt(self, webpage):
        return self._search_regex(r'{"passedToken":"([A-Za-z0-9-_]*\.[A-Za-z0-9-_]*\.[A-Za-z0-9-_]+)",', webpage, 'jwt')

    def _check_if_logged_in(self, webpage):
        if '{ member: null' in webpage:
            raise self.raise_login_required(method='cookies')

    def _real_extract(self, url):

Review comment (security):
```suggestion
            headers = {'Authorization': f'Bearer {jwt}'}
```
avoid +ing strings

Code after:
    _VALID_URL = r'https://app.itpro.tv/course/(?P<course>[\w-]+)/(?P<id>[\w-]+)'
    _TESTS = [{
        'url': 'https://app.itpro.tv/course/guided-tour/introductionitprotv',
        'md5': 'bca4a28c2667fd1a63052e71a94bb88c',
        'info_dict': {
            'id': 'introductionitprotv',
            'ext': 'mp4',
            'title': 'An Introduction to ITProTV 101',
            'thumbnail': 'https://itprotv-image-bucket.s3.amazonaws.com/getting-started/itprotv-101-introduction-PGM.11_39_56_02.Still001.png',
            'description': 'md5:b175c2c3061ce35a4dd33865b2c1da4e',
            'duration': 269,
            'series': 'ITProTV 101',
            'series_id': 'guided-tour',
            'availability': 'needs_auth',
            'chapter': 'ITProTV 101',
            'chapter_number': 1,
            'chapter_id': '5dbb3de426b46c0010b5d1b6'
        },
    },
        {
        'url': 'https://app.itpro.tv/course/beyond-tech/job-interview-tips',
        'md5': '101a299b98c47ccf4c67f9f0951defa8',
        'info_dict': {
            'id': 'job-interview-tips',
            'ext': 'mp4',
            'title': 'Job Interview Tips',
            'thumbnail': 'https://s3.amazonaws.com:443/production-itprotv-thumbnails/2f370bf5-294d-4bbe-ab80-c0b5781630ea.png',
            'description': 'md5:30d8ba483febdf89ec85623aad3c3cb6',
            'duration': 267,
            'series': 'Beyond Tech',
            'series_id': 'beyond-tech',
            'availability': 'needs_auth',
            'chapter': 'Job Development',
            'chapter_number': 2,
            'chapter_id': '5f7c78d424330c000edf04d9'
        },
    }]

    def _real_extract(self, url):
        episode_id, course_name = self._match_valid_url(url).group('id', 'course')
        webpage = self._download_webpage(url, episode_id)
        self._check_if_logged_in(webpage)
        course = self._call_api('course', course_name, webpage)
        episode = self._call_api('episode', episode_id, webpage)

        chapter_number, chapter = next((
            (i, topic) for i, topic in enumerate(course.get('topics') or [], 1)
            if traverse_obj(topic, 'id') == episode.get('topic')), {})

        return {
            'id': episode_id,