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

Code before:
        resp = self._download_json(
            'https://graphql.api.dailymotion.com/', None, note, data=json.dumps({
                'operationName': 'SEARCH_QUERY',
                'query': search_query,
                'variables': {
                    'limit': 20,
                    'page': page,
                    'query': term,
                    'shouldIncludeChannels': False,
                    'shouldIncludeLives': False,
                    'shouldIncludePlaylists': False,
                    'shouldIncludeTopics': False,
                    'shouldIncludeVideos': True
                }
            }).encode(), headers=self._HEADERS)
        obj = traverse_obj(resp, ('data', 'search', {dict}))
        if not obj:
            raise ExtractorError(traverse_obj(resp, ('errors', 0, 'message'))
                                 or 'Could not fetch search data', expected=True)
        return obj

    def _fetch_page(self, term, page):
        page += 1
        response = self._call_search_api(term, page, f'Searching "{term}" page {page}')
        for edge in traverse_obj(response, ('videos', 'edges', lambda _, x: x['node']['xid'])) or []:
            xid = edge['node']['xid']
            yield self.url_result(f'https://www.dailymotion.com/video/{xid}', DailymotionIE, xid)

    def _real_extract(self, url):
        term = urllib.parse.unquote_plus(self._match_id(url))
        return self.playlist_result(
            OnDemandPagedList(functools.partial(self._fetch_page, term), self._PAGE_SIZE), term, term)


class DailymotionUserIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:user'
    _VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/(?!(?:embed|swf|#|video|playlist|search)/)(?:(?:old/)?user/)?(?P<id>[^/]+)'
    _TESTS = [{
        'url': 'https://www.dailymotion.com/user/nqtv',
        'info_dict': {
            'id': 'nqtv',
        },
        'playlist_mincount': 152,
    }, {
        'url': 'http://www.dailymotion.com/user/UnderProject',
        'info_dict': {
            'id': 'UnderProject',
        },
        'playlist_mincount': 1000,
        'skip': 'Takes too long time',
    }, {

Review comment (suggestion):
```suggestion
        for xid in traverse_obj(response, ('videos', 'edges', ..., 'node', 'xid')):
```

Code after:
        'info_dict': {
            'id': 'king of turtles',
            'title': 'king of turtles',
        },
        'playlist_mincount': 90,
    }]
    _SEARCH_QUERY = 'query SEARCH_QUERY( $query: String! $page: Int $limit: Int ) { search { videos( query: $query first: $limit page: $page ) { edges { node { xid } } } } } '

    def _call_search_api(self, term, page, note):
        if not self._HEADERS.get('Authorization'):
            self._HEADERS['Authorization'] = f'Bearer {self._get_token(term)}'
        resp = self._download_json(
            'https://graphql.api.dailymotion.com/', None, note, data=json.dumps({
                'operationName': 'SEARCH_QUERY',
                'query': self._SEARCH_QUERY,
                'variables': {
                    'limit': 20,
                    'page': page,
                    'query': term,
                }
            }).encode(), headers=self._HEADERS)
        obj = traverse_obj(resp, ('data', 'search', {dict}))
        if not obj:
            raise ExtractorError(
                traverse_obj(resp, ('errors', 0, 'message', {str})) or 'Could not fetch search data')

        return obj

    def _fetch_page(self, term, page):
        page += 1
        response = self._call_search_api(term, page, f'Searching "{term}" page {page}')
        for xid in traverse_obj(response, ('videos', 'edges', ..., 'node', 'xid')):
            yield self.url_result(f'https://www.dailymotion.com/video/{xid}', DailymotionIE, xid)

    def _real_extract(self, url):
        term = urllib.parse.unquote_plus(self._match_id(url))
        return self.playlist_result(
            OnDemandPagedList(functools.partial(self._fetch_page, term), self._PAGE_SIZE), term, term)


class DailymotionUserIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:user'
    _VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/(?!(?:embed|swf|#|video|playlist|search)/)(?:(?:old/)?user/)?(?P<id>[^/?#]+)'
    _TESTS = [{
        'url': 'https://www.dailymotion.com/user/nqtv',
        'info_dict': {
            'id': 'nqtv',
        },
        'playlist_mincount': 152,
    }, {
        'url': 'http://www.dailymotion.com/user/UnderProject',