bt4g.py 3.2 KB

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