diff --git a/docs/dev/engines/online/adobe_stock.rst b/docs/dev/engines/online/adobe_stock.rst deleted file mode 100644 index 752ce87cb..000000000 --- a/docs/dev/engines/online/adobe_stock.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _adobe stock engine: - -=========== -Adobe Stock -=========== - -.. automodule:: searx.engines.adobe_stock - :members: diff --git a/searx/engines/adobe_stock.py b/searx/engines/adobe_stock.py deleted file mode 100644 index a4ab11290..000000000 --- a/searx/engines/adobe_stock.py +++ /dev/null @@ -1,221 +0,0 @@ -# SPDX-License-Identifier: AGPL-3.0-or-later -"""`Adobe Stock`_ is a service that gives access to millions of royalty-free -assets. Assets types include photos, vectors, illustrations, templates, 3D -assets, videos, motion graphics templates and audio tracks. - -.. Adobe Stock: https://stock.adobe.com/ - -Configuration -============= - -The engine has the following mandatory setting: - -- SearXNG's :ref:`engine categories` -- Adobe-Stock's :py:obj:`adobe_order` -- Adobe-Stock's :py:obj:`adobe_content_types` - -.. code:: yaml - - - name: adobe stock - engine: adobe_stock - shortcut: asi - categories: [images] - adobe_order: relevance - adobe_content_types: ["photo", "illustration", "zip_vector", "template", "3d", "image"] - - - name: adobe stock video - engine: adobe_stock - network: adobe stock - shortcut: asi - categories: [videos] - adobe_order: relevance - adobe_content_types: ["video"] - -Implementation -============== - -""" -import typing as t -from datetime import datetime, timedelta -from urllib.parse import urlencode - -import isodate - -about = { - "website": "https://stock.adobe.com/", - "wikidata_id": "Q5977430", - "official_api_documentation": None, - "use_official_api": False, - "require_api_key": False, - "results": "JSON", -} - -categories = [] -paging = True -results_per_page = 10 - -base_url = "https://stock.adobe.com" - -adobe_order: str = "" -"""Sort order, can be one of: - -- ``relevance`` or -- ``featured`` or -- ``creation`` (most recent) or -- ``nb_downloads`` (number of downloads) -""" - -ADOBE_VALID_TYPES = ["photo", "illustration", "zip_vector", "video", "template", "3d", "audio", "image"] -adobe_content_types: list = [] -"""A list of of content types. The following content types are offered: - -- Images: ``image`` -- Videos: ``video`` -- Templates: ``template`` -- 3D: ``3d`` -- Audio ``audio`` - -Additional subcategories: - -- Photos: ``photo`` -- Illustrations: ``illustration`` -- Vectors: ``zip_vector`` (Vectors), -""" - -# Do we need support for "free_collection" and "include_stock_enterprise"? - - -def setup(_: dict[str, t.Any]) -> bool | None: - if not categories: - raise ValueError("adobe_stock engine: categories is unset") - - # adobe_order - if not adobe_order: - raise ValueError("adobe_stock engine: adobe_order is unset") - if adobe_order not in ["relevance", "featured", "creation", "nb_downloads"]: - raise ValueError(f"unsupported adobe_order: {adobe_order}") - - # adobe_content_types - if not adobe_content_types: - raise ValueError("adobe_stock engine: adobe_content_types is unset") - - if isinstance(adobe_content_types, list): - for content_type in adobe_content_types: - if content_type not in ADOBE_VALID_TYPES: - raise ValueError("adobe_stock engine: adobe_content_types: '%s' is invalid" % content_type) - else: - raise ValueError( - "adobe_stock engine: adobe_content_types must be a list of strings not %s" % type(adobe_content_types) - ) - - -def request(query, params): - - args = { - "k": query, - "limit": results_per_page, - "order": adobe_order, - "search_page": params["pageno"], - "search_type": "pagination", - } - - for content_type in ADOBE_VALID_TYPES: - args[f"filters[content_type:{content_type}]"] = 1 if content_type in adobe_content_types else 0 - - params["url"] = f"{base_url}/de/Ajax/Search?{urlencode(args)}" - - # headers required to bypass bot-detection - if params["searxng_locale"] == "all": - params["headers"]["Accept-Language"] = "en-US,en;q=0.5" - - return params - - -def parse_image_item(item): - return { - "template": "images.html", - "url": item["content_url"], - "title": item["title"], - "content": item["asset_type"], - "img_src": item["content_thumb_extra_large_url"], - "thumbnail_src": item["thumbnail_url"], - "resolution": f"{item['content_original_width']}x{item['content_original_height']}", - "img_format": item["format"], - "author": item["author"], - } - - -def parse_video_item(item): - - # in video items, the title is more or less a "content description", we try - # to reduce the length of the title .. - - title = item["title"] - content = "" - if "." in title.strip()[:-1]: - content = title - title = title.split(".", 1)[0] - elif "," in title: - content = title - title = title.split(",", 1)[0] - elif len(title) > 50: - content = title - title = "" - for w in content.split(" "): - title += f" {w}" - if len(title) > 50: - title = title.strip() + "\u2026" - break - - return { - "template": "videos.html", - "url": item["content_url"], - "title": title, - "content": content, - # https://en.wikipedia.org/wiki/ISO_8601#Durations - "length": isodate.parse_duration(item["time_duration"]), - "publishedDate": datetime.fromisoformat(item["creation_date"]), - "thumbnail": item["thumbnail_url"], - "iframe_src": item["video_small_preview_url"], - "metadata": item["asset_type"], - } - - -def parse_audio_item(item): - audio_data = item["audio_data"] - content = audio_data.get("description") or "" - if audio_data.get("album"): - content = audio_data["album"] + " - " + content - - return { - "url": item["content_url"], - "title": item["title"], - "content": content, - # "thumbnail": base_url + item["thumbnail_url"], - "iframe_src": audio_data["preview"]["url"], - "publishedDate": datetime.fromisoformat(audio_data["release_date"]) if audio_data["release_date"] else None, - "length": timedelta(seconds=round(audio_data["duration"] / 1000)) if audio_data["duration"] else None, - "author": item.get("artist_name"), - } - - -def response(resp): - results = [] - - json_resp = resp.json() - - if isinstance(json_resp["items"], list): - return None - for item in json_resp["items"].values(): - if item["asset_type"].lower() in ["image", "premium-image", "illustration", "vector"]: - result = parse_image_item(item) - elif item["asset_type"].lower() == "video": - result = parse_video_item(item) - elif item["asset_type"].lower() == "audio": - result = parse_audio_item(item) - else: - logger.error("no handle for %s --> %s", item["asset_type"], item) - continue - results.append(result) - - return results diff --git a/searx/settings.yml b/searx/settings.yml index 40f72a05d..f447cd9c1 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -335,36 +335,6 @@ engines: shortcut: acf disabled: true - - name: adobe stock - engine: adobe_stock - shortcut: asi - categories: ["images"] - # https://docs.searxng.org/dev/engines/online/adobe_stock.html - adobe_order: relevance - adobe_content_types: ["photo", "illustration", "zip_vector", "template", "3d", "image"] - timeout: 6 - disabled: true - - - name: adobe stock video - engine: adobe_stock - shortcut: asv - network: adobe stock - categories: ["videos"] - adobe_order: relevance - adobe_content_types: ["video"] - timeout: 6 - disabled: true - - - name: adobe stock audio - engine: adobe_stock - shortcut: asa - network: adobe stock - categories: ["music"] - adobe_order: relevance - adobe_content_types: ["audio"] - timeout: 6 - disabled: true - - name: astrophysics data system engine: astrophysics_data_system shortcut: ads