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

Code before:
        },
        'playlist_mincount': 31,
    }, {
        'url': 'https://www.khanacademy.org/computing/computer-science',
        'info_dict': {
            'id': 'computer-science',
            'title': 'Computer science theory',
            'description': 'md5:4b472a4646e6cf6ec4ccb52c4062f8ba',
        },
        'playlist_mincount': 50,
    }]

    def _parse_component_props(self, component_props, display_id):
        course = component_props['course']
        unit = traverse_obj(course, ('unitChildren', lambda _, v: v['relativeUrl'] == f'/{display_id}'), get_all=False)
        # unit should traverse to None when url is course-level

        entries = traverse_obj([unit] if unit else course['unitChildren'], (
            ..., 'allOrderedChildren', ..., 'curatedChildren', lambda _, v: v['contentKind'] == 'Video',
            {lambda x: self.url_result(urljoin('https://www.khanacademy.org', x['canonicalUrl']), KhanAcademyIE)}))

        return self.playlist_result(entries, **traverse_obj(unit or course, {
            'id': ('slug', {str}),
            'title': ('translatedTitle', {str}),
            'description': ('translatedDescription', {str}),
        }))


Review comment (suggestion):
I am tempted to change the ID here to the actual ID instead of the slug. The slug seems like a value that could be the same across different courses.
Do you think that makes sense?
```suggestion
        return self.playlist_result(
            entries,
            display_id=display_id,
            **traverse_obj(selected_unit, {
                'id': ('id', {str}),
                'title': ('translatedTitle', {str}),
                'description': ('translatedDescription', {str}),
                '_old_archive_ids': ('slug', {str}, {lambda x: make_archive_id(self, x)}),
            }))
```

Code after:
            'id': 'x48c910b6',
            'title': 'Cryptography',
            'description': 'How have humans protected their secret messages through history? What has changed today?',
            'display_id': 'computing/computer-science/cryptography',
            '_old_archive_ids': ['khanacademyunit cryptography'],
        },
        'playlist_mincount': 31,
    }, {
        'url': 'https://www.khanacademy.org/computing/computer-science',
        'info_dict': {
            'id': 'x301707a0',
            'title': 'Computer science theory',
            'description': 'md5:4b472a4646e6cf6ec4ccb52c4062f8ba',
            'display_id': 'computing/computer-science',
            '_old_archive_ids': ['khanacademyunit computer-science'],
        },
        'playlist_mincount': 50,
    }]

    def _parse_component_props(self, component_props, display_id):
        course = component_props['course']
        selected_unit = traverse_obj(course, (
            'unitChildren', lambda _, v: v['relativeUrl'] == f'/{display_id}', any)) or course

        def build_entry(entry):
            return self.url_result(urljoin(
                'https://www.khanacademy.org', entry['canonicalUrl']),
                KhanAcademyIE, title=entry.get('translatedTitle'))

        entries = traverse_obj(selected_unit, (
            (('unitChildren', ...), None), 'allOrderedChildren', ..., 'curatedChildren',
            lambda _, v: v['contentKind'] == 'Video' and v['canonicalUrl'], {build_entry}))

        return self.playlist_result(
            entries,
            display_id=display_id,
            **traverse_obj(selected_unit, {
                'id': ('id', {str}),
                'title': ('translatedTitle', {str}),
                'description': ('translatedDescription', {str}),
                '_old_archive_ids': ('slug', {str}, {lambda x: [make_archive_id(self, x)] if x else None}),
            }))