vysion 1.0.15__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vysion
3
- Version: 1.0.15
3
+ Version: 2.0.0
4
4
  Summary: The official Python client library for Vysion
5
5
  Home-page: https://vysion.ai
6
6
  License: Apache-2.0
@@ -29,9 +29,9 @@ Welcome to the PyPi webpage for Vysion, our implementation as a Python library t
29
29
 
30
30
  You can request a demo for the web app or an API-key to use in this library at [vysion.ai](https://vysion.ai).
31
31
 
32
- Latest version: [1.0.15](https://pypi.org/project/vysion/)
32
+ Latest version: [2.0.0](https://pypi.org/project/vysion/)
33
33
 
34
- You can visit [the documentation](https://developers.vysion.ai/?python) or our [repository] (https://github.com/ByronLabs/vysion-py/tree/main) for more information on the searches and requests performed with the library or directly on the API.
34
+ You can visit [the documentation](https://developers.vysion.ai/?python) for more information on the searches and requests performed with the library or directly on the API.
35
35
 
36
36
  ### Taxonomy
37
37
 
@@ -4,9 +4,9 @@ Welcome to the PyPi webpage for Vysion, our implementation as a Python library t
4
4
 
5
5
  You can request a demo for the web app or an API-key to use in this library at [vysion.ai](https://vysion.ai).
6
6
 
7
- Latest version: [1.0.15](https://pypi.org/project/vysion/)
7
+ Latest version: [2.0.0](https://pypi.org/project/vysion/)
8
8
 
9
- You can visit [the documentation](https://developers.vysion.ai/?python) or our [repository] (https://github.com/ByronLabs/vysion-py/tree/main) for more information on the searches and requests performed with the library or directly on the API.
9
+ You can visit [the documentation](https://developers.vysion.ai/?python) for more information on the searches and requests performed with the library or directly on the API.
10
10
 
11
11
  ### Taxonomy
12
12
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "vysion"
3
- version = "1.0.15"
3
+ version = "2.0.0"
4
4
  description = "The official Python client library for Vysion"
5
5
  homepage = "https://vysion.ai"
6
6
  repository = "https://gitlab.com/byronlabs/vysion/vysion-py"
@@ -32,7 +32,10 @@ python-dotenv = "0.19.2"
32
32
  flake8 = "4.0.1"
33
33
  pyflakes = "2.4.0"
34
34
  mypy = "^0.961"
35
- black = "^22.6.0"
35
+ black = "^24.3.0"
36
+
37
+ [tool.poetry.group.dev.dependencies]
38
+ ruff = "^0.5.2"
36
39
 
37
40
  [build-system]
38
41
  requires = ["poetry-core>=1.0.0"]
@@ -18,23 +18,22 @@ limitations under the License.
18
18
  # TODO Referenciar vt-py
19
19
 
20
20
  import logging
21
+ import os
21
22
  from datetime import datetime, timedelta
22
23
  from typing import Union
23
- from urllib.parse import urlencode, urljoin, quote
24
+ from urllib.parse import quote, urlencode, urljoin
24
25
 
25
26
  # from pydantic import validate_arguments
26
27
  import requests
27
28
 
28
29
  import vysion.dto as dto
29
30
  from vysion.client.error import APIError
30
- from vysion.dto import VysionError
31
+ from vysion.dto import Error
31
32
  from vysion.version import __version__ as vysion_version
32
33
 
33
- import os
34
-
35
34
  # All API endpoints start with this prefix, you don't need to include the
36
35
  # prefix in the paths you request as it's prepended automatically.
37
- _ENDPOINT_PREFIX = "/api/v1/"
36
+ _ENDPOINT_PREFIX = "/api/v2/"
38
37
 
39
38
  LOGGER = logging.getLogger("vysion-py")
40
39
  LOGGER.setLevel(logging.INFO)
@@ -43,12 +42,10 @@ LOGGER.setLevel(logging.INFO)
43
42
 
44
43
 
45
44
  class BaseClient:
46
-
47
45
  # __attrs__ = []
48
46
 
49
47
  # @validate_arguments #
50
48
  def __init__(self, api_key: str = None, headers: dict = dict(), proxy: dict = None):
51
-
52
49
  assert api_key is not None, "API key MUST be provided"
53
50
  assert isinstance(api_key, str), "API key MUST be a string"
54
51
 
@@ -57,14 +54,12 @@ class BaseClient:
57
54
  self.headers = headers
58
55
 
59
56
  def __get_session__(self) -> requests.Session:
60
-
61
57
  # TODO Configure proxy
62
58
 
63
59
  # If session is undefined
64
60
  try:
65
61
  self._session
66
62
  except (NameError, AttributeError):
67
-
68
63
  headers = self.headers.copy()
69
64
  headers.update(
70
65
  {
@@ -80,7 +75,6 @@ class BaseClient:
80
75
  return self._session
81
76
 
82
77
  def _get_api_host(self):
83
-
84
78
  if os.getenv("API_HOST") is not None:
85
79
  api_host = os.getenv("API_HOST")
86
80
 
@@ -88,14 +82,15 @@ class BaseClient:
88
82
  api_host = "https://api.vysion.ai"
89
83
 
90
84
  return api_host
91
-
92
85
 
93
- def _build_api_url__(self, endpoint, param, **query_params):
94
-
95
- param = quote(param, safe='')
86
+ def _build_api_url__(self, endpoint, param=None, **query_params):
96
87
  _API_HOST = self._get_api_host()
97
88
  _BASE_API = urljoin(_API_HOST, _ENDPOINT_PREFIX)
98
- base = urljoin(_BASE_API, f"{endpoint}/{param}")
89
+ base = urljoin(_BASE_API, endpoint)
90
+
91
+ if param is not None:
92
+ param = quote(param, safe="")
93
+ base = urljoin(_BASE_API, f"{endpoint}/{param}")
99
94
 
100
95
  query_params_initialzed = query_params.copy()
101
96
 
@@ -103,19 +98,17 @@ class BaseClient:
103
98
  keys.sort()
104
99
 
105
100
  for i in keys:
106
-
107
101
  v = query_params[i]
108
102
 
109
103
  if v is None:
110
104
  del query_params_initialzed[i]
111
105
 
112
106
  query = "?" + urlencode(query_params_initialzed)
113
-
114
107
  return urljoin(base, query)
115
108
 
116
109
  def _make_request(self, url: str) -> dto.VysionResponse:
117
-
118
110
  session = self.__get_session__()
111
+ print(url)
119
112
  r = session.get(url)
120
113
 
121
114
  # TODO Improve this
@@ -137,251 +130,255 @@ class BaseClient:
137
130
  return result
138
131
 
139
132
 
140
- def vysion_error_manager(method) -> Union[dto.Result, VysionError]:
133
+ def vysion_error_manager(method) -> Union[dto.VysionResponse, Error]:
141
134
  def manage(*args, **kwargs):
142
135
  try:
143
136
  result = method(*args, **kwargs)
144
137
  return result
145
138
  except APIError as e:
146
- return VysionError(code=e.code, message=e.message)
139
+ return Error(code=e.code, message=e.message)
147
140
  except Exception as e:
148
141
  LOGGER.error(e)
149
- return VysionError()
142
+ return Error()
150
143
 
151
144
  return manage
152
145
 
153
146
 
154
147
  class Client(BaseClient):
155
-
156
- # def add_url(self, url:str, type:VysionURL.Type):
157
- # """Add a Tor URL to be analyzed by PARCHE.
158
-
159
- # :param url: URL to be scanned.
160
- # :param type: Instance of :class:`VysionURL.Type`
161
- # :returns: An instance of :class:`VysionResponse`
162
- # """
163
- # pass
164
-
165
- # def find_onion(self):
166
- # pass
167
-
168
- # def add_onion(self):
169
- # pass
170
-
171
- # def consume_feed(self):
172
- # pass
173
-
174
148
  @vysion_error_manager
175
149
  def status(self):
176
150
  # TODO Check API status
177
151
  pass
178
152
 
153
+ #
154
+ # Darknet document search
155
+ #
156
+
179
157
  @vysion_error_manager
180
158
  def search(
181
159
  self,
182
- query: str,
183
- tag: str = None,
184
- notTag: str = None,
185
- exact: bool = False,
186
- network: dto.Network = None,
187
- language: dto.Language = None,
188
- page: int = 1,
160
+ q: str,
189
161
  lte: datetime = None,
190
162
  gte: datetime = None,
191
- ) -> dto.Result:
192
-
163
+ page: int = 1,
164
+ page_size: int = 10,
165
+ network: dto.Network = None,
166
+ language: dto.Language = None,
167
+ include_tag: str = None,
168
+ exclude_tag: str = None,
169
+ ) -> dto.VysionResponse:
193
170
  url = self._build_api_url__(
194
- "search",
195
- query,
196
- tag=tag,
197
- notTag=notTag,
198
- exact=exact,
199
- network=network,
200
- language=language,
201
- page=page,
171
+ "document/search",
172
+ q=q,
202
173
  lte=lte,
203
174
  gte=gte,
175
+ page=page,
176
+ page_size=page_size,
177
+ network=network,
178
+ language=language,
179
+ include_tag=include_tag,
180
+ exclude_tag=exclude_tag,
204
181
  )
205
182
 
206
183
  result = self._make_request(url)
207
184
  return result.data
208
-
209
- @vysion_error_manager
210
- def search_telegram(
211
- self,
212
- query: str,
213
- username: str = None,
214
- page: int = 1,
215
- lte: datetime = None,
216
- gte: datetime = None,
217
- ) -> dto.Result:
218
185
 
219
- url = self._build_api_url__(
220
- "search-telegram",
221
- query,
222
- username=username,
223
- page=page,
224
- lte=lte,
225
- gte=gte,
226
- )
186
+ @vysion_error_manager
187
+ def get_document(self, document_id: str) -> dto.VysionResponse:
188
+ url = self._build_api_url__("document", document_id)
227
189
 
228
190
  result = self._make_request(url)
229
191
  return result.data
230
192
 
231
193
  @vysion_error_manager
232
- def fuzzy_search(
194
+ def find_url(
233
195
  self,
234
- query: str,
235
- tag: str = None,
236
- notTag: str = None,
237
- network: dto.Network = None,
238
- language: dto.Language = None,
196
+ url: str,
239
197
  page: int = 1,
240
198
  lte: datetime = None,
241
199
  gte: datetime = None,
242
- ) -> dto.Result:
243
-
244
- url = self._build_api_url__(
245
- "fuzzy",
246
- query,
247
- tag=tag,
248
- notTag=notTag,
249
- network=network,
250
- language=language,
251
- page=page,
252
- lte=lte,
253
- gte=gte,
254
- )
200
+ ) -> dto.VysionResponse:
201
+ url = self._build_api_url__("document/url", url, page=page, lte=lte, gte=gte)
255
202
 
256
203
  result = self._make_request(url)
257
204
  return result.data
258
205
 
259
206
  @vysion_error_manager
260
- def find_btc(
261
- self, btc: str, page: int = 1, lte: datetime = None, gte: datetime = None
262
- ) -> dto.Result:
263
-
264
- url = self._build_api_url__("btc", btc, page=page, lte=lte, gte=gte)
207
+ def get_tag(self, tag: str) -> dto.VysionResponse:
208
+ url = self._build_api_url__("document/tag", tag)
265
209
 
266
210
  result = self._make_request(url)
267
211
  return result.data
268
212
 
269
213
  @vysion_error_manager
270
- def find_eth(
271
- self, eth: str, page: int = 1, lte: datetime = None, gte: datetime = None
272
- ) -> dto.Result:
273
-
274
- url = self._build_api_url__("eth", eth, page=page, lte=lte, gte=gte)
214
+ def find_email(
215
+ self, email: str, page: int = 1, lte: datetime = None, gte: datetime = None
216
+ ) -> dto.VysionResponse:
217
+ url = self._build_api_url__(
218
+ "document/email", email, page=page, lte=lte, gte=gte
219
+ )
275
220
 
276
221
  result = self._make_request(url)
277
222
  return result.data
278
223
 
279
224
  @vysion_error_manager
280
- def find_dot(
281
- self, dot: str, page: int = 1, lte: datetime = None, gte: datetime = None
282
- ) -> dto.Result:
283
-
284
- url = self._build_api_url__("dot", dot, page=page, lte=lte, gte=gte)
225
+ def find_wallet(
226
+ self,
227
+ chain: str,
228
+ address: str,
229
+ page: int = 1,
230
+ lte: datetime = None,
231
+ gte: datetime = None,
232
+ ) -> dto.VysionResponse:
233
+ url = self._build_api_url__(
234
+ "document/wallet", chain + "/" + address, page=page, lte=lte, gte=gte
235
+ )
285
236
 
286
237
  result = self._make_request(url)
287
238
  return result.data
288
239
 
289
240
  @vysion_error_manager
290
- def find_xrp(
291
- self, xrp: str, page: int = 1, lte: datetime = None, gte: datetime = None
292
- ) -> dto.Result:
241
+ def get_document_html(self, document_id: str) -> str:
242
+ url = self._build_api_url__("html", document_id)
293
243
 
294
- url = self._build_api_url__("xrp", xrp, page=page, lte=lte, gte=gte)
244
+ result = requests.get(url)
245
+
246
+ return result.text
247
+
248
+ #
249
+ # Ransowmare Victims Search
250
+ #
251
+
252
+ @vysion_error_manager
253
+ def search_ransomware_victim(
254
+ self,
255
+ q: str,
256
+ lte: datetime = None,
257
+ gte: datetime = None,
258
+ page: int = 1,
259
+ page_size: int = 10,
260
+ network: dto.Network = None,
261
+ country: str = None,
262
+ language: dto.Language = None,
263
+ ) -> dto.VysionResponse:
264
+ url = self._build_api_url__(
265
+ "victim/search",
266
+ q=q,
267
+ lte=lte,
268
+ gte=gte,
269
+ page=page,
270
+ page_size=page_size,
271
+ network=network,
272
+ country=country,
273
+ language=language,
274
+ )
295
275
 
296
276
  result = self._make_request(url)
297
277
  return result.data
298
278
 
299
- @vysion_error_manager
300
- def find_xmr(
301
- self, xmr: str, page: int = 1, lte: datetime = None, gte: datetime = None
302
- ) -> dto.Result:
279
+ #
280
+ # Ransomware Stats
281
+ #
303
282
 
304
- url = self._build_api_url__("xmr", xmr, page=page, lte=lte, gte=gte)
283
+ @vysion_error_manager
284
+ def ransomware_countries_stats(
285
+ self,
286
+ gte: datetime = None,
287
+ lte: datetime = None,
288
+ ) -> dto.VysionResponse[dto.Stat]:
289
+ url = self._build_api_url__("stats/countries", gte=gte, lte=lte)
305
290
 
306
291
  result = self._make_request(url)
307
292
  return result.data
308
293
 
309
294
  @vysion_error_manager
310
- def find_zec(
311
- self, zec: str, page: int = 1, lte: datetime = None, gte: datetime = None
312
- ) -> dto.Result:
313
-
314
- url = self._build_api_url__("zec", zec, page=page, lte=lte, gte=gte)
295
+ def ransomware_groups_stats(
296
+ self,
297
+ gte: datetime = None,
298
+ lte: datetime = None,
299
+ ) -> dto.VysionResponse[dto.Stat]:
300
+ url = self._build_api_url__("stats/groups", gte=gte, lte=lte)
315
301
 
316
302
  result = self._make_request(url)
317
303
  return result.data
318
304
 
319
- # TODO find_domain?
320
305
  @vysion_error_manager
321
- def find_url(
306
+ def ransomware_attacks_stats(
322
307
  self,
323
- query_url: str,
324
- page: int = 1,
325
- lte: datetime = None,
326
308
  gte: datetime = None,
327
- ) -> dto.Result:
328
-
329
- url = self._build_api_url__("url", query_url, page=page, lte=lte, gte=gte)
309
+ lte: datetime = None,
310
+ ) -> dto.VysionResponse[dto.Stat]:
311
+ url = self._build_api_url__("stats/attacks", gte=gte, lte=lte)
330
312
 
331
313
  result = self._make_request(url)
332
314
  return result.data
333
315
 
334
- @vysion_error_manager
335
- def find_email(
336
- self, email: str, page: int = 1, lte: datetime = None, gte: datetime = None
337
- ) -> dto.Result:
316
+ #
317
+ # IM Search
318
+ #
338
319
 
339
- url = self._build_api_url__("email", email, page=page, lte=lte, gte=gte)
320
+ @vysion_error_manager
321
+ def search_im(
322
+ self,
323
+ platform: str,
324
+ q: str,
325
+ gte: datetime = None,
326
+ lte: datetime = None,
327
+ page: int = 1,
328
+ username: str = None,
329
+ ) -> dto.VysionResponse[dto.ImMessageHit]:
330
+ url = self._build_api_url__(
331
+ "im/" + platform + "/search",
332
+ q=q,
333
+ gte=gte,
334
+ lte=lte,
335
+ page=page,
336
+ username=username,
337
+ )
340
338
 
341
339
  result = self._make_request(url)
342
340
  return result.data
343
341
 
344
342
  @vysion_error_manager
345
- def get_document(self, document_id: str) -> dto.Result:
346
-
347
- url = self._build_api_url__("document", document_id)
343
+ def get_im_chat(
344
+ self, platform: str, channelId: str
345
+ ) -> dto.VysionResponse[dto.ImMessageHit]:
346
+ url = self._build_api_url__("im/" + platform + "/chat/", channelId)
348
347
 
349
348
  result = self._make_request(url)
350
349
  return result.data
351
350
 
352
351
  @vysion_error_manager
353
- def get_tag(self, tag: str) -> dto.Result:
354
-
355
- url = self._build_api_url__("tag", tag)
352
+ def get_im_profile(
353
+ self, platform: str, userId: str
354
+ ) -> dto.VysionResponse[dto.ImProfileHit]:
355
+ url = self._build_api_url__("im/" + platform + "/profile/", userId)
356
356
 
357
357
  result = self._make_request(url)
358
358
  return result.data
359
-
360
- @vysion_error_manager
361
- def get_chat_telegram(
362
- self,
363
- channelId: str,
364
- lte:datetime = None,
365
- gte: datetime = None,
366
- ) -> dto.Result:
367
359
 
368
- url = self._build_api_url__("telegram/chat", channelId, lte=lte, gte=gte)
360
+ @vysion_error_manager
361
+ def get_im_message(
362
+ self, platform: str, messageId: str
363
+ ) -> dto.VysionResponse[dto.ImMessageHit]:
364
+ url = self._build_api_url__("im/" + platform + "/message/", messageId)
369
365
 
370
366
  result = self._make_request(url)
371
367
  return result.data
372
-
373
- @vysion_error_manager
374
- def get_message_telegram(
375
- self,
376
- id: str,
377
- ) -> dto.Result:
378
368
 
379
- url = self._build_api_url__("telegram/message", id)
369
+ @vysion_error_manager
370
+ def get_im_channel(
371
+ self, platform: str, channelId: str
372
+ ) -> dto.VysionResponse[dto.ImChannelHit]:
373
+ url = self._build_api_url__("im/" + platform + "/channel/", channelId)
380
374
 
381
375
  result = self._make_request(url)
382
376
  return result.data
383
377
 
378
+ #
384
379
  # FEEDS
380
+ #
381
+
385
382
  @vysion_error_manager
386
383
  def consume_feed_ransomware(self, batch_day: datetime = datetime.today()):
387
384
  pass
@@ -401,7 +398,6 @@ class DaylyFeed(Client):
401
398
 
402
399
  class RansomwareFeed(DaylyFeed):
403
400
  def _consume_batch(self, start_time, end_time):
404
-
405
401
  days = (datetime.now() - start_time).days
406
402
  pages = (end_time - start_time).days
407
403
 
@@ -410,4 +406,4 @@ class RansomwareFeed(DaylyFeed):
410
406
  yield self._make_request(url)
411
407
 
412
408
 
413
- # TODO /api/v1/feeds
409
+ # TODO /api/v1/feeds
@@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
  See the License for the specific language governing permissions and
15
15
  limitations under the License.
16
16
  """
17
- from vysion.dto import VysionError
17
+ from vysion.dto import Error
18
18
 
19
19
 
20
20
  class APIError(Exception):
@@ -28,8 +28,8 @@ class APIError(Exception):
28
28
 
29
29
  super().__init__()
30
30
 
31
- if code not in [i.value for i in VysionError.StatusCode]:
32
- self.code = VysionError.StatusCode.UNK
31
+ if code not in [i.value for i in Error.StatusCode]:
32
+ self.code = Error.StatusCode.UNK
33
33
  self.message = f"{message} (Original code: {code})"
34
34
  else:
35
35
  self.code = code