bt4g.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """BT4G_ (bt4g.com) is not a tracker and doesn't store any content and only
  3. collects torrent metadata (such as file names and file sizes) and a magnet link
  4. (torrent identifier).
  5. This engine does not parse the HTML page because there is an API in XML (RSS).
  6. The RSS feed provides fewer data like amount of seeders/leechers and the files
  7. in the torrent file. It's a tradeoff for a "stable" engine as the XML from RSS
  8. content will change way less than the HTML page.
  9. .. _BT4G: https://bt4g.com/
  10. Configuration
  11. =============
  12. The engine has the following additional settings:
  13. - :py:obj:`bt4g_order_by`
  14. - :py:obj:`bt4g_category`
  15. With this options a SearXNG maintainer is able to configure **additional**
  16. engines for specific torrent searches. For example a engine to search only for
  17. Movies and sort the result list by the count of seeders.
  18. .. code:: yaml
  19. - name: bt4g.movie
  20. engine: bt4g
  21. shortcut: bt4gv
  22. categories: video
  23. bt4g_order_by: seeders
  24. bt4g_category: 'movie'
  25. Implementations
  26. ===============
  27. """
  28. import re
  29. from datetime import datetime
  30. from urllib.parse import quote
  31. from lxml import etree
  32. from searx.utils import get_torrent_size
  33. # about
  34. about = {
  35. "website": 'https://bt4gprx.com',
  36. "use_official_api": False,
  37. "require_api_key": False,
  38. "results": 'XML',
  39. }
  40. # engine dependent config
  41. categories = ['files']
  42. paging = True
  43. time_range_support = True
  44. # search-url
  45. url = 'https://bt4gprx.com'
  46. search_url = url + '/search?q={search_term}&orderby={order_by}&category={category}&p={pageno}&page=rss'
  47. bt4g_order_by = 'relevance'
  48. """Result list can be ordered by ``relevance`` (default), ``size``, ``seeders``
  49. or ``time``.
  50. .. hint::
  51. When *time_range* is activate, the results always ordered by ``time``.
  52. """
  53. bt4g_category = 'all'
  54. """BT$G offers categories: ``all`` (default), ``audio``, ``movie``, ``doc``,
  55. ``app`` and `` other``.
  56. """
  57. def request(query, params):
  58. order_by = bt4g_order_by
  59. if params['time_range']:
  60. order_by = 'time'
  61. params['url'] = search_url.format(
  62. search_term=quote(query),
  63. order_by=order_by,
  64. category=bt4g_category,
  65. pageno=params['pageno'],
  66. )
  67. return params
  68. def response(resp):
  69. results = []
  70. search_results = etree.XML(resp.content)
  71. # return empty array if nothing is found
  72. if len(search_results) == 0:
  73. return []
  74. for entry in search_results.xpath('./channel/item'):
  75. title = entry.find("title").text
  76. link = entry.find("guid").text
  77. fullDescription = entry.find("description").text.split('<br>')
  78. filesize = fullDescription[1]
  79. filesizeParsed = re.split(r"([A-Z]+)", filesize)
  80. magnetlink = entry.find("link").text
  81. pubDate = entry.find("pubDate").text
  82. results.append(
  83. {
  84. 'url': link,
  85. 'title': title,
  86. 'magnetlink': magnetlink,
  87. 'seed': 'N/A',
  88. 'leech': 'N/A',
  89. 'filesize': get_torrent_size(filesizeParsed[0], filesizeParsed[1]),
  90. 'publishedDate': datetime.strptime(pubDate, '%a,%d %b %Y %H:%M:%S %z'),
  91. 'template': 'torrent.html',
  92. }
  93. )
  94. return results