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

Code before:

class DailymotionPlaylistIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:playlist'
    _VALID_URL = r'(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/playlist/(?P<id>x[0-9a-z]+)'
    _TESTS = [{
        'url': 'http://www.dailymotion.com/playlist/xv4bw_nqtv_sport/1#video=xl8v3q',
        'info_dict': {
            'id': 'xv4bw',
        },
        'playlist_mincount': 20,
    }]
    _OBJECT_TYPE = 'collection'

    @classmethod
    def _extract_embed_urls(cls, url, webpage):
        # Look for embedded Dailymotion playlist player (#3822)
        for mobj in re.finditer(
                r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?dailymotion\.[a-z]{2,3}/widget/jukebox\?.+?)\1',
                webpage):
            for p in re.findall(r'list\[\]=/playlist/([^/]+)/', unescapeHTML(mobj.group('url'))):
                yield '//dailymotion.com/playlist/%s' % p


class DailymotionSearchIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:search'
    _VALID_URL = r'(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/search/(?P<id>[^/]+)/videos'
    _PAGE_SIZE = 20
    _TESTS = [{
        'url': 'http://www.dailymotion.com/search/king of turtles/videos',
        'info_dict': {
            'id': 'king of turtles',
            'title': 'king of turtles',
        },
        'playlist_mincount': 90,
    }]

    def _call_search_api(self, term, page, note):
        search_query = 'query SEARCH_QUERY( $query: String! $page: Int $limit: Int ) { search { videos( query: $query first: $limit page: $page ) { edges { node { xid } } } } } '

        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': search_query,
                'variables': {
                    'limit': 20,
                    'page': page,
                    'query': term,
                }
            }).encode(), headers=self._HEADERS)

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/search/(?P<id>[^/?#]+)/videos'
```

Code after:
            entries, playlist_id)


class DailymotionPlaylistIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:playlist'
    _VALID_URL = r'(?:https?://)?(?:www\.)?dailymotion\.[a-z]{2,3}/playlist/(?P<id>x[0-9a-z]+)'
    _TESTS = [{
        'url': 'http://www.dailymotion.com/playlist/xv4bw_nqtv_sport/1#video=xl8v3q',
        'info_dict': {
            'id': 'xv4bw',
        },
        'playlist_mincount': 20,
    }]
    _OBJECT_TYPE = 'collection'

    @classmethod
    def _extract_embed_urls(cls, url, webpage):
        # Look for embedded Dailymotion playlist player (#3822)
        for mobj in re.finditer(
                r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?dailymotion\.[a-z]{2,3}/widget/jukebox\?.+?)\1',
                webpage):
            for p in re.findall(r'list\[\]=/playlist/([^/]+)/', unescapeHTML(mobj.group('url'))):
                yield '//dailymotion.com/playlist/%s' % p


class DailymotionSearchIE(DailymotionPlaylistBaseIE):
    IE_NAME = 'dailymotion:search'
    _VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/search/(?P<id>[^/?#]+)/videos'
    _PAGE_SIZE = 20
    _TESTS = [{
        'url': 'http://www.dailymotion.com/search/king of turtles/videos',
        '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,
                }