| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | # SPDX-License-Identifier: AGPL-3.0-or-later"""DuckDuckGo Extra (images, videos, news)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"""from datetime import datetimefrom typing import TYPE_CHECKINGfrom urllib.parse import urlencodefrom searx.engines.duckduckgo import fetch_traits  # pylint: disable=unused-importfrom searx.engines.duckduckgo import (    get_ddg_lang,    get_vqd,)from searx.enginelib.traits import EngineTraitsif TYPE_CHECKING:    import logging    logger: logging.Loggertraits: EngineTraits# aboutabout = {    "website": 'https://duckduckgo.com/',    "wikidata_id": 'Q12805',    "use_official_api": False,    "require_api_key": False,    "results": 'JSON (site requires js to get images)',}# engine dependent configcategories = ['images', 'web']ddg_category = 'images'"""The category must be any of ``images``, ``videos`` and ``news``"""paging = Truesafesearch = Truesend_accept_language_header = Truesafesearch_cookies = {0: '-2', 1: None, 2: '1'}safesearch_args = {0: '1', 1: None, 2: '1'}search_path_map = {'images': 'i', 'videos': 'v', 'news': 'news'}def request(query, params):    # request needs a vqd argument    vqd = get_vqd(query)    if not vqd:        # some search terms do not have results and therefore no vqd value        params['url'] = None        return params    eng_region = traits.get_region(params['searxng_locale'], traits.all_locale)    eng_lang = get_ddg_lang(traits, params['searxng_locale'])    args = {        'q': query,        'o': 'json',        # 'u': 'bing',        'l': eng_region,        'f': ',,,,,',        'vqd': vqd,    }    if params['pageno'] > 1:        args['s'] = (params['pageno'] - 1) * 100    params['cookies']['ad'] = eng_lang  # zh_CN    params['cookies']['ah'] = eng_region  # "us-en,de-de"    params['cookies']['l'] = eng_region  # "hk-tzh"    safe_search = safesearch_cookies.get(params['safesearch'])    if safe_search is not None:        params['cookies']['p'] = safe_search  # "-2", "1"    safe_search = safesearch_args.get(params['safesearch'])    if safe_search is not None:        args['p'] = safe_search  # "-1", "1"    logger.debug("cookies: %s", params['cookies'])    params['url'] = f'https://duckduckgo.com/{search_path_map[ddg_category]}.js?{urlencode(args)}'    return paramsdef _image_result(result):    return {        'template': 'images.html',        'url': result['url'],        'title': result['title'],        'content': '',        'thumbnail_src': result['thumbnail'],        'img_src': result['image'],        'img_format': '%s x %s' % (result['width'], result['height']),        'source': result['source'],    }def _video_result(result):    return {        'template': 'videos.html',        'url': result['content'],        'title': result['title'],        'content': result['description'],        'thumbnail': result['images'].get('small') or result['images'].get('medium'),        'iframe_src': result['embed_url'],        'source': result['provider'],        'length': result['duration'],        'metadata': result.get('uploader'),    }def _news_result(result):    return {        'url': result['url'],        'title': result['title'],        'content': result['excerpt'],        'source': result['source'],        'publishedDate': datetime.utcfromtimestamp(result['date']),    }def response(resp):    results = []    res_json = resp.json()    for result in res_json['results']:        if ddg_category == 'images':            results.append(_image_result(result))        elif ddg_category == 'videos':            results.append(_video_result(result))        elif ddg_category == 'news':            results.append(_news_result(result))        else:            raise ValueError(f"Invalid duckduckgo category: {ddg_category}")    return results
 |