voidlinux.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # lint: pylint
  3. """SearXNG engine for `Void Linux binary packages`_. Void is a general purpose
  4. operating system, based on the monolithic Linux kernel. Its package system
  5. allows you to quickly install, update and remove software; software is provided
  6. in binary packages or can be built directly from sources with the help of the
  7. XBPS source packages collection.
  8. .. _Void Linux binary packages: https://voidlinux.org/packages/
  9. """
  10. import re
  11. from urllib.parse import quote_plus
  12. from searx.utils import humanize_bytes
  13. about = {
  14. 'website': 'https://voidlinux.org/packages/',
  15. 'wikidata_id': 'Q19310966',
  16. 'use_official_api': True,
  17. 'official_api_documentation': None,
  18. 'require_api_key': False,
  19. 'results': 'JSON',
  20. }
  21. categories = ['packages', 'it']
  22. base_url = "https://xq-api.voidlinux.org"
  23. pkg_repo_url = "https://github.com/void-linux/void-packages"
  24. void_arch = 'x86_64'
  25. """Default architecture to search for. For valid values see :py:obj:`ARCH_RE`"""
  26. ARCH_RE = re.compile('aarch64-musl|armv6l-musl|armv7l-musl|x86_64-musl|aarch64|armv6l|armv7l|i686|x86_64')
  27. """Regular expresion that match a architecture in the query string."""
  28. def request(query, params):
  29. arch_path = ARCH_RE.search(query)
  30. if arch_path:
  31. arch_path = arch_path.group(0)
  32. query = query.replace(arch_path, '').strip()
  33. else:
  34. arch_path = void_arch
  35. params['url'] = f"{base_url}/v1/query/{arch_path}?q={quote_plus(query)}"
  36. return params
  37. def response(resp):
  38. """
  39. At Void Linux, several packages sometimes share the same source code
  40. (template) and therefore also have the same URL. Results with identical
  41. URLs are merged as one result for SearXNG.
  42. """
  43. packages = {}
  44. for result in resp.json()['data']:
  45. # 32bit and dbg packages don't have their own package templates
  46. github_slug = re.sub(r"-(32bit|dbg)$", "", result['name'])
  47. pkg_url = f"{pkg_repo_url}/tree/master/srcpkgs/{github_slug}"
  48. pkg_list = packages.get(pkg_url, [])
  49. pkg_list.append(
  50. {
  51. 'title': result['name'],
  52. 'content': f"{result['short_desc']} - {humanize_bytes(result['filename_size'])}",
  53. 'package_name': result['name'],
  54. 'version': f"v{result['version']}_{result['revision']}",
  55. 'tags': result['repository'],
  56. }
  57. )
  58. packages[pkg_url] = pkg_list
  59. results = []
  60. for pkg_url, pkg_list in packages.items():
  61. results.append(
  62. {
  63. 'url': pkg_url,
  64. 'template': 'packages.html',
  65. 'title': ' | '.join(x['title'] for x in pkg_list),
  66. 'content': pkg_list[0]['content'],
  67. 'package_name': ' | '.join(x['package_name'] for x in pkg_list),
  68. 'version': pkg_list[0]['version'],
  69. 'tags': [x['tags'] for x in pkg_list],
  70. }
  71. )
  72. return results