instances.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. ########################################################################
  2. # Searx-Qt - Lightweight desktop application for Searx.
  3. # Copyright (C) 2020-2022 CYBERDEViL
  4. #
  5. # This file is part of Searx-Qt.
  6. #
  7. # Searx-Qt is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Searx-Qt is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. import time
  22. from searxqt.core import log
  23. from searxqt.core.handler import HandlerProto, NetworkTypes
  24. from searxqt.core.instanceVersions import InstanceVersion
  25. from searxqt.core.requests import JsonResult, ErrorType, Schemas
  26. class SearchEngine:
  27. def __init__(self, name, data):
  28. """Model for a search engine data.
  29. @param name: Name of the search engine
  30. @type name: str
  31. @param data: Data of the search engine
  32. @type data: dict
  33. """
  34. self._name = name
  35. self._data = data
  36. def __repr__(self): return self._name
  37. @property
  38. def name(self):
  39. """
  40. @return: returns the name of this search engine.
  41. @rtype: str
  42. """
  43. return self._name
  44. class TLS:
  45. def __init__(self, data):
  46. """Model for a instance it's TLS data.
  47. @param data: dict with the instance it's TLS data.
  48. @type data: dict
  49. """
  50. self._data = data
  51. @property
  52. def data(self): return self._data
  53. @property
  54. def version(self):
  55. """Returns the TLS version used.
  56. @return:
  57. @rtype: str
  58. """
  59. return self.data.get('version', "")
  60. @property
  61. def certificate(self):
  62. """Returns a TLSCertificate object.
  63. @return:
  64. @rtype: TLSCertificate
  65. """
  66. return TLSCertificate(self.data.get('certificate', {}))
  67. class TLSCertificate:
  68. def __init__(self, data):
  69. """Model for a instance it's TLS certificate-data.
  70. @param data: dict with the instance it's TLS certificate-data.
  71. @type data: dict
  72. """
  73. self._data = data
  74. @property
  75. def data(self): return self._data
  76. @property
  77. def version(self):
  78. """
  79. @return:
  80. @rtype: int
  81. """
  82. return self.data.get('version', 0)
  83. @property
  84. def issuer(self):
  85. """
  86. @return:
  87. @rtype: TLSCertificateIssuer
  88. """
  89. return TLSCertificateIssuer(self.data.get('issuer', {}))
  90. class TLSCertificateIssuer:
  91. def __init__(self, data):
  92. """Model for a instance it's TLS certificate-issuer-data.
  93. @param data: dict with the instance it's
  94. TLS certificate-issuer-data.
  95. @type data: dict
  96. """
  97. self._data = data
  98. @property
  99. def data(self): return self._data
  100. @property
  101. def commonName(self):
  102. """
  103. @rtype: str
  104. """
  105. return self.data.get('commonName', "")
  106. @property
  107. def countryName(self):
  108. """
  109. @rtype: str
  110. """
  111. return self.data.get('countryName', "")
  112. @property
  113. def organizationName(self):
  114. """
  115. @rtype: str
  116. """
  117. return self.data.get('organizationName', "")
  118. class Network:
  119. def __init__(self, data):
  120. """Model for a instance it's network data.
  121. @param data: dict with the instance it's network data.
  122. @type data: dict
  123. """
  124. self._data = data
  125. @property
  126. def data(self): return self._data
  127. @property
  128. def ipv6(self):
  129. """
  130. @return: If ipv6 is enabled on this instance.
  131. @rtype: bool
  132. """
  133. return self.data.get('ipv6', False)
  134. @property
  135. def ips(self):
  136. """
  137. @return: A list with NetworkIP objects
  138. @rtype: list
  139. """
  140. return [NetworkIP(ip, data)
  141. for ip, data in self.data.get('ips', {}).items()]
  142. @property
  143. def asnPrivacy(self):
  144. """
  145. @return: -1 no asn privacy, 0 asn privacy, -2 unknown.
  146. @rtype: int
  147. """
  148. return self.data.get('asn_privacy', -2)
  149. class NetworkIP:
  150. def __init__(self, ip, data):
  151. """Model for a network ip data.
  152. @param ip: ip address
  153. @type ip: str
  154. @param data: dict with a network ip data.
  155. @type data: dict
  156. """
  157. self._ip = ip
  158. self._data = data
  159. def __repr__(self):
  160. return (
  161. f"IP: {self.ip} Reverse: {self.reverse} " \
  162. f"FieldType: {self.fieldType} asnCidr: {self.asnCidr}"
  163. )
  164. def __str__(self): return repr(self)
  165. @property
  166. def ip(self):
  167. """
  168. @return: ip address
  169. @rtype: str
  170. """
  171. return self._ip
  172. @property
  173. def data(self): return self._data
  174. @property
  175. def reverse(self):
  176. """
  177. @return:
  178. @rtype: str
  179. """
  180. return self.data.get('reverse', None)
  181. @property
  182. def fieldType(self):
  183. """
  184. @return: Record type
  185. @rtype: str
  186. """
  187. return self.data.get('field_type', None)
  188. @property
  189. def asnCidr(self):
  190. """
  191. @return:
  192. @rtype: str
  193. """
  194. return self.data.get('asn_cidr', None)
  195. @property
  196. def httpsPort(self):
  197. """
  198. @return:
  199. @rtype: bool
  200. """
  201. return self.data.get('https_port', None)
  202. class Instance:
  203. def __init__(self, url, data):
  204. """Model for a SearX instance.
  205. @param url: Url of the instance
  206. @type url: str
  207. @param data: Data of the instance
  208. @type data: dict
  209. """
  210. self._url = url
  211. self._data = data
  212. self._version = InstanceVersion(self._data.get('version', ''))
  213. if not self._version.isValid():
  214. log.debug(f"Invalid version {self._version}: {self._version.error()}", cls=Instance)
  215. def __str__(self): return self.url
  216. def __repr__(self): return str(self)
  217. @property
  218. def data(self): return self._data
  219. @property
  220. def url(self):
  221. """
  222. @return: returns the url of this instance.
  223. @rtype: str
  224. """
  225. return self._url
  226. @property
  227. def main(self):
  228. """Returns False when not set.
  229. @return: ?
  230. @rtype: bool
  231. """
  232. return self._data.get('main', False)
  233. @property
  234. def networkType(self):
  235. """ Network type; see core/handler.py:NetworkTypes
  236. @return: Network protocol used (Web, Tor, I2P from NetworkTypes)
  237. @rtype: int
  238. """
  239. return self._data.get('network_type', 0)
  240. @property
  241. def version(self):
  242. """Returns a empty string when none found.
  243. @return: Returns the instance it's version.
  244. @rtype: InstanceVersion
  245. """
  246. return self._version
  247. @property
  248. def engines(self):
  249. """
  250. Returns a empty string when none found.
  251. @return: Returns a list with SearchEngine objects
  252. @rtype: list
  253. """
  254. return [SearchEngine(name, data) for name, data in self._data.get(
  255. 'engines', {}).items()]
  256. @property
  257. def tls(self):
  258. """
  259. @rtype: TLS
  260. """
  261. return TLS(self._data.get('tls', {}))
  262. @property
  263. def network(self):
  264. """
  265. @rtype: Network
  266. """
  267. return Network(self._data.get('network', {}))
  268. class Stats2Result(JsonResult):
  269. Schema = Schemas['searx_space_instances']
  270. def __init__(self, url, response, err="", errType=ErrorType.Success):
  271. JsonResult.__init__(self, url, response, err=err, errType=errType)
  272. class Stats2(HandlerProto):
  273. """ This class holds the instances.json data and will be passed
  274. to other classes (Instances, Engines)
  275. """
  276. URL = "https://searx.space/"
  277. def __init__(self, requestsHandler):
  278. HandlerProto.__init__(self, requestsHandler)
  279. def updateInstances(self):
  280. """Fetches instances.json from a searx-stats2 instance.
  281. @param requestKwargs: Kwargs to pass to requests.get
  282. @type requestKwargs: dict
  283. @return: A tuple (bool Success/Failed, str Message)
  284. @rtype: tuple
  285. """
  286. url = Stats2.URL.rstrip('/') + '/data/instances.json'
  287. result = self.requestsHandler.get(url, ResultType=Stats2Result)
  288. if result:
  289. self.setData(result.json())
  290. self._lastUpdated = time.time()
  291. # Processing (use our own definition of network types
  292. for url, data in self.instances.items():
  293. data.update({"network_type": NetworkTypes.netTypeFromUrl(url)})
  294. return result