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

Code before:
        }

    def _extract_entries(self, video_ids, metainfo, list_id):
        entries = [{**metainfo, **self._extract_video(id)} for id in set(video_ids)]
        return self.playlist_result(entries, **metainfo, id=list_id)

    def _real_extract(self, url):
        video_id = self._match_id(url)
        query = {self._INFO_QUERY_KEY: video_id}

        data = traverse_obj(
            self._get_api(self._INFO_API, video_id, query=query), self._DATA_PATH)

        video_ids = traverse_obj(data, self._ID_PATH)
        metainfo = traverse_obj(data, self._META_PATH)
        return self._extract_entries(video_ids, metainfo, video_id)


class TapTapIntlBase(TapTapBaseIE):
    _X_UA = 'V=1&PN=WebAppIntl2&LANG=zh_TW&VN_CODE=115&VN=0.1.0&LOC=CN&PLT=PC&DS=Android&UID={uuid}&CURR=&DT=PC&OS=Windows&OSV=NT%208.0.0'
    _VIDEO_API = 'https://www.taptap.io/webapiv2/video-resource/v1/multi-get'


class TapTapMomentIE(TapTapBaseIE):
    _VALID_URL = r'https?://www\.taptap\.cn/moment/(?P<id>\d+)'
    _INFO_API = 'https://www.taptap.cn/webapiv2/moment/v3/detail'
    _ID_PATH = ('moment', 'topic', (('videos', ...), 'pin_video'), 'video_id')
    _META_PATH = ('moment', {
        'timestamp': ('created_time', {int_or_none}),
        'uploader': ('author', 'user', 'name', {str}),
        'title': ('topic', 'title', {str}),
        'description': ('topic', 'summary', {str}),
    })
    _TESTS = [{
        'url': 'https://www.taptap.cn/moment/194618230982052443',
        'info_dict': {
            'id': '194618230982052443',
            'title': '《崩坏3》开放世界「后崩坏书」新篇章 于淹没之地仰视辰星',
            'description': 'md5:cf66f7819d413641b8b28c8543f4ecda',
            'timestamp': 1633453402,
            'upload_date': '20211005',
            'uploader': '乌酱',
        },
        'playlist_count': 1,
        'playlist': [{
            'info_dict': {
                'id': '2202584',
                'ext': 'mp4',
                'title': '《崩坏3》开放世界「后崩坏书」新篇章 于淹没之地仰视辰星',
                'description': 'md5:cf66f7819d413641b8b28c8543f4ecda',
                'duration': 66,

Review comment (security):
Some additional metadata
```suggestion
        'modified_timestamp': ('edited_time', {int_or_none}),
        'uploader': ('author', 'user', 'name', {str}),
        'uploader_id': ('author', 'user', 'id', {int}, {str_or_none}),
```

Code after:
        }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        query = {self._INFO_QUERY_KEY: video_id}

        data = traverse_obj(
            self._get_api(self._INFO_API, video_id, query=query), self._DATA_PATH)

        metainfo = traverse_obj(data, self._META_PATH)
        entries = [{
            **metainfo,
            **self._extract_video(id)
        } for id in set(traverse_obj(data, self._ID_PATH))]

        return self.playlist_result(entries, **metainfo, id=video_id)


class TapTapMomentIE(TapTapBaseIE):
    _VALID_URL = r'https?://www\.taptap\.cn/moment/(?P<id>\d+)'
    _INFO_API = 'https://www.taptap.cn/webapiv2/moment/v3/detail'
    _ID_PATH = ('moment', 'topic', (('videos', ...), 'pin_video'), 'video_id')
    _META_PATH = ('moment', {
        'timestamp': ('created_time', {int_or_none}),
        'modified_timestamp': ('edited_time', {int_or_none}),
        'uploader': ('author', 'user', 'name', {str}),
        'uploader_id': ('author', 'user', 'id', {int}, {str_or_none}),
        'title': ('topic', 'title', {str}),
        'description': ('topic', 'summary', {str}),
    })
    _TESTS = [{
        'url': 'https://www.taptap.cn/moment/194618230982052443',
        'info_dict': {
            'id': '194618230982052443',
            'title': '《崩坏3》开放世界「后崩坏书」新篇章 于淹没之地仰视辰星',
            'description': 'md5:cf66f7819d413641b8b28c8543f4ecda',
            'timestamp': 1633453402,
            'upload_date': '20211005',
            'modified_timestamp': 1633453402,
            'modified_date': '20211005',
            'uploader': '乌酱',
            'uploader_id': '532896',
        },
        'playlist_count': 1,
        'playlist': [{
            'info_dict': {
                'id': '2202584',
                'ext': 'mp4',
                'title': '《崩坏3》开放世界「后崩坏书」新篇章 于淹没之地仰视辰星',
                'description': 'md5:cf66f7819d413641b8b28c8543f4ecda',
                'duration': 66,