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

Code before:
            video_url = traverse_obj(url, ('url', {url_or_none}))
            if video_url:
                formats.append({
                    'format': self._FORMATS.get(name),
                    'format_id': name,
                    'url': video_url,
                    'quality': self._QUALITIES.get(name),
                    'ext': 'ts' if '.m3u8' in video_url else determine_ext(video_url),
                    **parse_resolution(self._RESOLUTIONS.get(name))
                })
            else:
                self.to_screen(
                    f'"{self._FORMATS.get(name, name)}" format may require logging in. {self._login_hint()}')

        return {
            'id': video_id,
            'formats': formats,
            **traverse_obj(video_info, ('DATA', {
                'title': ('content', 'title', {str_or_none}),
                'uploader': ('content', 'author', {str_or_none}),
                'uploader_id': ('content', 'up_id', {str_or_none}),
                'duration': ('content', 'video_duration', {int_or_none}),
                'thumbnail': ('content', 'video_pic', {url_or_none}),
                'timestamp': ('content', 'create_time', {int_or_none}),
                'view_count': ('content', 'view_num', {int_or_none}),
                'tags': ('videoTag', ..., 'tagName', {str_or_none}),
            }))
        }


Review comment (security):
We only want to transform with `{str_or_none}` when we want to stringify any value that is not `None`, whether it be int or dict, etc
Otherwise we want to just expect type with `{str}`
```suggestion
                'title': ('content', 'title', {str}),
                'uploader': ('content', 'author', {str}),
                'uploader_id': ('content', 'up_id', {str_or_none}),
                'duration': ('content', 'video_duration', {int_or_none}),
                'thumbnail': ('content', 'video_pic', {url_or_none}),
                'timestamp': ('content', 'create_time', {int_or_none}),
                'view_count': ('content', 'view_num', {int_or_none}),
                'tags': ('videoTag', ..., 'tagName', {str}),
```

Code after:
        for name, url in traverse_obj(url_info, ('data', 'thumb_video', {dict.items}, ...)):
            video_url = traverse_obj(url, ('url', {url_or_none}))
            if video_url:
                ext = determine_ext(video_url)
                formats.append({
                    'format': self._FORMATS.get(name),
                    'format_id': name,
                    'url': video_url,
                    'quality': self._QUALITIES.get(name),
                    'ext': 'mp4' if ext == 'm3u8' else ext,
                    'protocol': 'm3u8_native' if ext == 'm3u8' else 'https',
                    **parse_resolution(self._RESOLUTIONS.get(name))
                })
            else:
                self.to_screen(
                    f'"{self._FORMATS.get(name, name)}" format may require logging in. {self._login_hint()}')

        return {
            'id': video_id,
            'formats': formats,
            **traverse_obj(video_info, ('DATA', {
                'title': ('content', 'title', {str}),
                'uploader': ('content', 'author', {str}),
                'uploader_id': ('content', 'up_id', {str_or_none}),
                'duration': ('content', 'video_duration', {int_or_none}),
                'thumbnail': ('content', 'video_pic', {url_or_none}),
                'timestamp': ('content', 'create_time', {int_or_none}),
                'view_count': ('content', 'view_num', {int_or_none}),
                'tags': ('videoTag', ..., 'tagName', {str}),
            }))
        }