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

Code before:
        kwargs['query'] = query
        return super(YoutubeBaseInfoExtractor, self)._download_webpage_handle(
            *args, **compat_kwargs(kwargs))

    def _real_initialize(self):
        if self._downloader is None:
            return
        if not self._login():
            return

    _DEFAULT_API_DATA = {
        'context': {
            'client': {
                'clientName': 'WEB',
                'clientVersion': '2.20201021.03.00',
            }
        },
    }

    _YT_INITIAL_DATA_RE = r'(?:window\s*\[\s*["\']ytInitialData["\']\s*\]|ytInitialData)\s*=\s*({.+?})\s*;'
    _YT_INITIAL_PLAYER_RESPONSE_RE = r'ytInitialPlayerResponse\s*=\s*({.+?})\s*;'
    _YT_INITIAL_BOUNDARY_RE = r'(?:var\s+meta|</script|\n)'

    def _generate_sapisidhash_header(self):
        sapisid_cookie = try_get(self._downloader.cookiejar._cookies, lambda x: x['.youtube.com']['/']['SAPISID'])
        if not hasattr(sapisid_cookie, 'value'):
            return  # TODO: Do something
        time_now = round(time.time())
        sapisidhash = hashlib.sha1((str(time_now) + " " + sapisid_cookie.value + " " + "https://www.youtube.com").encode("utf-8")).hexdigest()
        return "SAPISIDHASH %s_%s" % (time_now, sapisidhash)

    def _call_api(self, ep, query, video_id=None, fatal=True, headers=None,
                  note='Downloading API JSON', errnote='Unable to download API page'):

        data = self._DEFAULT_API_DATA.copy()
        data.update(query)
        headers = headers or {}
        headers.update({'content-type': 'application/json'})
        auth = self._generate_sapisidhash_header()
        if auth is not None:
            headers.update({'Authorization': auth, 'X-Origin': 'https://www.youtube.com'})

        return self._download_json(
            'https://www.youtube.com/youtubei/v1/%s' % ep,
            video_id=video_id, fatal=fatal, note=note, errnote=errnote,
            data=json.dumps(data).encode('utf8'), headers=headers,
            query={'key': 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'})

    def _extract_yt_initial_data(self, video_id, webpage):
        return self._parse_json(
            self._search_regex(

Review comment (suggestion):
`if not hasattr(sapisid_cookie, 'value'):`
tbh this could probably just be replaced by a None check, as its either a NoneType or Cookie object

Code after:
        kwargs['query'] = query
        return super(YoutubeBaseInfoExtractor, self)._download_webpage_handle(
            *args, **compat_kwargs(kwargs))

    def _real_initialize(self):
        if self._downloader is None:
            return
        if not self._login():
            return

    _DEFAULT_API_DATA = {
        'context': {
            'client': {
                'clientName': 'WEB',
                'clientVersion': '2.20210301.08.00',
            }
        },
    }

    _YT_INITIAL_DATA_RE = r'(?:window\s*\[\s*["\']ytInitialData["\']\s*\]|ytInitialData)\s*=\s*({.+?})\s*;'
    _YT_INITIAL_PLAYER_RESPONSE_RE = r'ytInitialPlayerResponse\s*=\s*({.+?})\s*;'
    _YT_INITIAL_BOUNDARY_RE = r'(?:var\s+meta|</script|\n)'

    def _generate_sapisidhash_header(self):
        sapisid_cookie = self._get_cookies('https://www.youtube.com').get('SAPISID')
        if sapisid_cookie is None:
            return
        time_now = round(time.time())
        sapisidhash = hashlib.sha1((str(time_now) + " " + sapisid_cookie.value + " " + "https://www.youtube.com").encode("utf-8")).hexdigest()
        return "SAPISIDHASH %s_%s" % (time_now, sapisidhash)

    def _call_api(self, ep, query, video_id, fatal=True, headers=None,
                  note='Downloading API JSON', errnote='Unable to download API page'):
        data = self._DEFAULT_API_DATA.copy()
        data.update(query)
        headers = headers or {}
        headers.update({'content-type': 'application/json'})
        auth = self._generate_sapisidhash_header()
        if auth is not None:
            headers.update({'Authorization': auth, 'X-Origin': 'https://www.youtube.com'})

        return self._download_json(
            'https://www.youtube.com/youtubei/v1/%s' % ep,
            video_id=video_id, fatal=fatal, note=note, errnote=errnote,
            data=json.dumps(data).encode('utf8'), headers=headers,
            query={'key': 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'})

    def _extract_yt_initial_data(self, video_id, webpage):
        return self._parse_json(
            self._search_regex(
                (r'%s\s*%s' % (self._YT_INITIAL_DATA_RE, self._YT_INITIAL_BOUNDARY_RE),