diff --git a/docs/admin/searx.favicons.rst b/docs/admin/searx.favicons.rst index d504e2c5e..8c18fca22 100644 --- a/docs/admin/searx.favicons.rst +++ b/docs/admin/searx.favicons.rst @@ -29,6 +29,7 @@ By default and without any extensions, SearXNG serves these resolvers: - ``duckduckgo`` - ``allesedv`` - ``google`` +- ``kagi`` - ``yandex`` With the above setting favicons are displayed, the user has the option to @@ -208,6 +209,7 @@ choose from, the following configuration could be used: "duckduckgo" = "searx.favicons.resolvers.duckduckgo" "allesedv" = "searx.favicons.resolvers.allesedv" # "google" = "searx.favicons.resolvers.google" + # "kagi" = "searx.favicons.resolvers.kagi" # "yandex" = "searx.favicons.resolvers.yandex" .. note:: @@ -226,6 +228,7 @@ into the *proxy*: - :py:obj:`searx.favicons.resolvers.duckduckgo` - :py:obj:`searx.favicons.resolvers.allesedv` - :py:obj:`searx.favicons.resolvers.google` +- :py:obj:`searx.favicons.resolvers.kagi` - :py:obj:`searx.favicons.resolvers.yandex` diff --git a/searx/favicons/favicons.toml b/searx/favicons/favicons.toml index 0e433d3aa..c4a9f4d79 100644 --- a/searx/favicons/favicons.toml +++ b/searx/favicons/favicons.toml @@ -13,6 +13,7 @@ cfg_schema = 1 # config's schema version no. # "duckduckgo" = "searx.favicons.resolvers.duckduckgo" # "allesedv" = "searx.favicons.resolvers.allesedv" # "google" = "searx.favicons.resolvers.google" +# "kagi" = "searx.favicons.resolvers.kagi" # "yandex" = "searx.favicons.resolvers.yandex" [favicons.cache] diff --git a/searx/favicons/resolvers.py b/searx/favicons/resolvers.py index 1c9e192b6..8007330b3 100644 --- a/searx/favicons/resolvers.py +++ b/searx/favicons/resolvers.py @@ -7,7 +7,7 @@ timeout``) and returns a tuple ``(data, mime)``. """ -__all__ = ["DEFAULT_RESOLVER_MAP", "allesedv", "duckduckgo", "google", "yandex"] +__all__ = ["DEFAULT_RESOLVER_MAP", "allesedv", "duckduckgo", "google", "kagi", "yandex"] from typing import Callable from searx import network @@ -76,6 +76,21 @@ def google(domain: str, timeout: int) -> tuple[None | bytes, None | str]: return data, mime +def kagi(domain: str, timeout: int) -> tuple[None | bytes, None | str]: + """Favicon Resolver from kagi.com / https://news.kagi.com/api/favicon-proxy""" + data, mime = (None, None) + # quality can be either 'fast' or 'best', best is slower and can return svgs (e.g. github.com) + url = f"https://news.kagi.com/api/favicon-proxy?domain={domain}&quality=fast" + logger.debug("fetch favicon from: %s", url) + + # will return a 404 if the favicon does not exist and a 200 if it does, + response = network.get(url, **_req_args(timeout=timeout)) + if response and response.status_code == 200: + mime = response.headers['Content-Type'] + data = response.content + return data, mime + + def yandex(domain: str, timeout: int) -> tuple[None | bytes, None | str]: """Favicon Resolver from yandex.com""" data, mime = (None, None) @@ -95,5 +110,6 @@ DEFAULT_RESOLVER_MAP = { "allesedv": allesedv, "duckduckgo": duckduckgo, "google": google, + "kagi": kagi, "yandex": yandex, } diff --git a/searx/settings.yml b/searx/settings.yml index 8d615cb87..ad605f256 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -47,7 +47,7 @@ search: # minimun characters to type before autocompleter starts autocomplete_min: 4 # backend for the favicon near URL in search results. - # Available resolvers: "allesedv", "duckduckgo", "google", "yandex" - leave blank to turn it off by default. + # Available resolvers: "allesedv", "duckduckgo", "google", "kagi", "yandex" - leave blank to turn it off by default. favicon_resolver: "" # Default search language - leave blank to detect from browser information or # use codes from 'languages.py'