favicon_resolver.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """This module implements functions needed for the favicon resolver.
  3. """
  4. # pylint: disable=use-dict-literal
  5. from httpx import HTTPError
  6. from searx import settings
  7. from searx.network import get as http_get, post as http_post
  8. from searx.exceptions import SearxEngineResponseException
  9. def update_kwargs(**kwargs):
  10. if 'timeout' not in kwargs:
  11. kwargs['timeout'] = settings['outgoing']['request_timeout']
  12. kwargs['raise_for_httperror'] = False
  13. def get(*args, **kwargs):
  14. update_kwargs(**kwargs)
  15. return http_get(*args, **kwargs)
  16. def post(*args, **kwargs):
  17. update_kwargs(**kwargs)
  18. return http_post(*args, **kwargs)
  19. def allesedv(domain):
  20. """Favicon Resolver from allesedv.com"""
  21. url = 'https://f1.allesedv.com/32/{domain}'
  22. # will just return a 200 regardless of the favicon existing or not
  23. # sometimes will be correct size, sometimes not
  24. response = get(url.format(domain=domain))
  25. # returns image/gif if the favicon does not exist
  26. if response.headers['Content-Type'] == 'image/gif':
  27. return []
  28. return response.content
  29. def duckduckgo(domain):
  30. """Favicon Resolver from duckduckgo.com"""
  31. url = 'https://icons.duckduckgo.com/ip2/{domain}.ico'
  32. # will return a 404 if the favicon does not exist and a 200 if it does,
  33. response = get(url.format(domain=domain))
  34. # api will respond with a 32x32 png image
  35. if response.status_code == 200:
  36. return response.content
  37. return []
  38. def google(domain):
  39. """Favicon Resolver from google.com"""
  40. url = 'https://www.google.com/s2/favicons?sz=32&domain={domain}'
  41. # will return a 404 if the favicon does not exist and a 200 if it does,
  42. response = get(url.format(domain=domain))
  43. # api will respond with a 32x32 png image
  44. if response.status_code == 200:
  45. return response.content
  46. return []
  47. def yandex(domain):
  48. """Favicon Resolver from yandex.com"""
  49. url = 'https://favicon.yandex.net/favicon/{domain}'
  50. # will always return 200
  51. response = get(url.format(domain=domain))
  52. # api will respond with a 16x16 png image, if it doesn't exist, it will be a 1x1 png image (70 bytes)
  53. if response.status_code == 200:
  54. if len(response.content) > 70:
  55. return response.content
  56. return []
  57. backends = {
  58. 'allesedv': allesedv,
  59. 'duckduckgo': duckduckgo,
  60. 'google': google,
  61. 'yandex': yandex,
  62. }
  63. def search_favicon(backend_name, domain):
  64. backend = backends.get(backend_name)
  65. if backend is None:
  66. return []
  67. try:
  68. return backend(domain)
  69. except (HTTPError, SearxEngineResponseException):
  70. return []