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

Code before:
        }
        return self.url_result(
            f'https://www.youtube.com/watch?v={video_id}', ie=YoutubeIE.ie_key(),
            video_id=video_id, video_title=title, **extra_info)

    @classmethod
    def _extract_next_notification_continuation_data(cls, renderer):
        # continuationItemRenderer
        ctoken = traverse_obj(
            renderer, ('continuationEndpoint', 'getNotificationMenuEndpoint', 'ctoken'), expected_type=str)
        if not ctoken:
            return
        return cls._build_notification_continuation_query(ctoken)

    @staticmethod
    def _build_notification_continuation_query(ctoken):
        query = {
            'ctoken': ctoken
        }
        return query

    def _notification_menu_entries(self, headers, max_requests):
        continuation_list = [None]
        request_count = 0
        entries = []
        while request_count < max_requests:
            query = {}
            if continuation_list[0]:
                query = self._extract_next_notification_continuation_data(continuation_list[0])
            request_count += 1
            response = self._extract_response(
                note=f'Downloading API JSON (page {request_count})',
                ep='notification/get_notification_menu', headers=headers,
                check_get_keys=['responseContext', 'actions', 'trackingParams'],
                item_id='notification_menu', query=query)
            for notification in self._extract_notification_menu(response, continuation_list) or []:
                entry = self._extract_notification(notification)
                if entry:
                    entries.append(entry)
            if not continuation_list[0]:
                break
        return entries

    def get_notifications(self, max_requests=1):
        return self._notification_menu_entries(self.generate_api_headers(), max_requests)

    def _real_extract(self, url):
        max_pages = int(self._match_valid_url(url).group('max_pages') or 1)
        self.write_debug(f'max_pages: {max_pages}')
        return self.playlist_result(
            entries=self.get_notifications(max_requests=max_pages), playlist_title='Notifications', ie=YoutubeTabIE.ie_key())

Review comment (suggestion):
```suggestion
        for page in itertools.count():
```

Code after:
        video_id = traverse_obj(
            notification, ('navigationEndpoint', 'watchEndpoint', 'videoId'), expected_type=str)
        url = f'https://www.youtube.com/watch?v={video_id}'
        channel_id = None
        if not video_id:
            browse_ep = traverse_obj(
                notification, ('navigationEndpoint', 'browseEndpoint'), expected_type=dict)
            channel_id = traverse_obj(browse_ep, 'browseId', expected_type=str)
            post_id = self._search_regex(
                r'/post/(.+)', traverse_obj(browse_ep, 'canonicalBaseUrl', expected_type=str),
                'post id', default=None)
            if not channel_id or not post_id:
                return
            # The direct /post url redirects to this in the browser
            url = f'https://www.youtube.com/channel/{channel_id}/community?lb={post_id}'

        channel = traverse_obj(
            notification, ('contextualMenu', 'menuRenderer', 'items', 1, 'menuServiceItemRenderer', 'text', 'runs', 1, 'text'),
            expected_type=str)
        title = self._search_regex(
            rf'{re.escape(channel)} [^:]+: (.+)', self._get_text(notification, 'shortMessage'),
            'video title', default=None)
        if title:
            title = title.replace('\xad', '')  # remove soft hyphens
        upload_date = (strftime_or_none(self._extract_time_text(notification, 'sentTimeText')[0], '%Y%m%d')
                       if self._configuration_arg('approximate_date', ie_key=YoutubeTabIE.ie_key())
                       else None)
        return {
            '_type': 'url',
            'url': url,
            'ie_key': (YoutubeIE if video_id else YoutubeTabIE).ie_key(),
            'video_id': video_id,
            'title': title,
            'channel_id': channel_id,
            'channel': channel,
            'thumbnails': self._extract_thumbnails(notification, 'videoThumbnail'),
            'upload_date': upload_date,
        }

    def _notification_menu_entries(self, ytcfg):
        continuation_list = [None]
        response = None
        for page in itertools.count(1):
            ctoken = traverse_obj(
                continuation_list, (0, 'continuationEndpoint', 'getNotificationMenuEndpoint', 'ctoken'), expected_type=str)
            response = self._extract_response(
                item_id=f'page {page}', query={'ctoken': ctoken} if ctoken else {}, ytcfg=ytcfg,
                ep='notification/get_notification_menu', check_get_keys='actions',
                headers=self.generate_api_headers(ytcfg=ytcfg, visitor_data=self._extract_visitor_data(response)))
            yield from self._extract_notification_menu(response, continuation_list)
            if not continuation_list[0]: