vysion 1.0.16__py3-none-any.whl → 2.0.1__py3-none-any.whl
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.
- vysion/client/client.py +151 -157
- vysion/client/error.py +3 -3
- vysion/dto/dto.py +205 -123
- vysion/dto/util.py +22 -21
- vysion/model/__init__.py +0 -1
- vysion/model/enum/languages.py +0 -1
- vysion/model/enum/networks.py +0 -1
- vysion/model/enum/ransom_groups.py +0 -1
- vysion/model/enum/services.py +0 -1
- vysion/taxonomy/taxonomy.py +0 -2
- vysion/version.py +1 -1
- {vysion-1.0.16.dist-info → vysion-2.0.1.dist-info}/METADATA +2 -2
- vysion-2.0.1.dist-info/RECORD +22 -0
- vysion/model/model.py +0 -184
- vysion-1.0.16.dist-info/RECORD +0 -23
- {vysion-1.0.16.dist-info → vysion-2.0.1.dist-info}/LICENSE +0 -0
- {vysion-1.0.16.dist-info → vysion-2.0.1.dist-info}/WHEEL +0 -0
vysion/client/client.py
CHANGED
|
@@ -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
|
|
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
|
|
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/
|
|
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,16 +82,14 @@ class BaseClient:
|
|
|
88
82
|
api_host = "https://api.vysion.ai"
|
|
89
83
|
|
|
90
84
|
return api_host
|
|
91
|
-
|
|
92
85
|
|
|
93
86
|
def _build_api_url__(self, endpoint, param=None, **query_params):
|
|
94
|
-
|
|
95
87
|
_API_HOST = self._get_api_host()
|
|
96
88
|
_BASE_API = urljoin(_API_HOST, _ENDPOINT_PREFIX)
|
|
97
|
-
base= urljoin(_BASE_API, endpoint)
|
|
89
|
+
base = urljoin(_BASE_API, endpoint)
|
|
98
90
|
|
|
99
91
|
if param is not None:
|
|
100
|
-
param = quote(param, safe=
|
|
92
|
+
param = quote(param, safe="")
|
|
101
93
|
base = urljoin(_BASE_API, f"{endpoint}/{param}")
|
|
102
94
|
|
|
103
95
|
query_params_initialzed = query_params.copy()
|
|
@@ -106,7 +98,6 @@ class BaseClient:
|
|
|
106
98
|
keys.sort()
|
|
107
99
|
|
|
108
100
|
for i in keys:
|
|
109
|
-
|
|
110
101
|
v = query_params[i]
|
|
111
102
|
|
|
112
103
|
if v is None:
|
|
@@ -116,8 +107,8 @@ class BaseClient:
|
|
|
116
107
|
return urljoin(base, query)
|
|
117
108
|
|
|
118
109
|
def _make_request(self, url: str) -> dto.VysionResponse:
|
|
119
|
-
|
|
120
110
|
session = self.__get_session__()
|
|
111
|
+
print(url)
|
|
121
112
|
r = session.get(url)
|
|
122
113
|
|
|
123
114
|
# TODO Improve this
|
|
@@ -139,251 +130,255 @@ class BaseClient:
|
|
|
139
130
|
return result
|
|
140
131
|
|
|
141
132
|
|
|
142
|
-
def vysion_error_manager(method) -> Union[dto.
|
|
133
|
+
def vysion_error_manager(method) -> Union[dto.VysionResponse, Error]:
|
|
143
134
|
def manage(*args, **kwargs):
|
|
144
135
|
try:
|
|
145
136
|
result = method(*args, **kwargs)
|
|
146
137
|
return result
|
|
147
138
|
except APIError as e:
|
|
148
|
-
return
|
|
139
|
+
return Error(code=e.code, message=e.message)
|
|
149
140
|
except Exception as e:
|
|
150
141
|
LOGGER.error(e)
|
|
151
|
-
return
|
|
142
|
+
return Error()
|
|
152
143
|
|
|
153
144
|
return manage
|
|
154
145
|
|
|
155
146
|
|
|
156
147
|
class Client(BaseClient):
|
|
157
|
-
|
|
158
|
-
# def add_url(self, url:str, type:VysionURL.Type):
|
|
159
|
-
# """Add a Tor URL to be analyzed by PARCHE.
|
|
160
|
-
|
|
161
|
-
# :param url: URL to be scanned.
|
|
162
|
-
# :param type: Instance of :class:`VysionURL.Type`
|
|
163
|
-
# :returns: An instance of :class:`VysionResponse`
|
|
164
|
-
# """
|
|
165
|
-
# pass
|
|
166
|
-
|
|
167
|
-
# def find_onion(self):
|
|
168
|
-
# pass
|
|
169
|
-
|
|
170
|
-
# def add_onion(self):
|
|
171
|
-
# pass
|
|
172
|
-
|
|
173
|
-
# def consume_feed(self):
|
|
174
|
-
# pass
|
|
175
|
-
|
|
176
148
|
@vysion_error_manager
|
|
177
149
|
def status(self):
|
|
178
150
|
# TODO Check API status
|
|
179
151
|
pass
|
|
180
152
|
|
|
153
|
+
#
|
|
154
|
+
# Darknet document search
|
|
155
|
+
#
|
|
156
|
+
|
|
181
157
|
@vysion_error_manager
|
|
182
158
|
def search(
|
|
183
159
|
self,
|
|
184
|
-
|
|
185
|
-
tag: str = None,
|
|
186
|
-
notTag: str = None,
|
|
187
|
-
exact: bool = False,
|
|
188
|
-
network: dto.Network = None,
|
|
189
|
-
language: dto.Language = None,
|
|
190
|
-
page: int = 1,
|
|
160
|
+
q: str,
|
|
191
161
|
lte: datetime = None,
|
|
192
162
|
gte: datetime = None,
|
|
193
|
-
|
|
194
|
-
|
|
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:
|
|
195
170
|
url = self._build_api_url__(
|
|
196
|
-
"search",
|
|
197
|
-
|
|
198
|
-
tag=tag,
|
|
199
|
-
notTag=notTag,
|
|
200
|
-
exact=exact,
|
|
201
|
-
network=network,
|
|
202
|
-
language=language,
|
|
203
|
-
page=page,
|
|
171
|
+
"document/search",
|
|
172
|
+
q=q,
|
|
204
173
|
lte=lte,
|
|
205
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,
|
|
206
181
|
)
|
|
207
182
|
|
|
208
183
|
result = self._make_request(url)
|
|
209
184
|
return result.data
|
|
210
|
-
|
|
211
|
-
@vysion_error_manager
|
|
212
|
-
def search_telegram(
|
|
213
|
-
self,
|
|
214
|
-
query: str,
|
|
215
|
-
username: str = None,
|
|
216
|
-
page: int = 1,
|
|
217
|
-
lte: datetime = None,
|
|
218
|
-
gte: datetime = None,
|
|
219
|
-
) -> dto.Result:
|
|
220
185
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
username=username,
|
|
225
|
-
page=page,
|
|
226
|
-
lte=lte,
|
|
227
|
-
gte=gte,
|
|
228
|
-
)
|
|
186
|
+
@vysion_error_manager
|
|
187
|
+
def get_document(self, document_id: str) -> dto.VysionResponse:
|
|
188
|
+
url = self._build_api_url__("document", document_id)
|
|
229
189
|
|
|
230
190
|
result = self._make_request(url)
|
|
231
191
|
return result.data
|
|
232
192
|
|
|
233
193
|
@vysion_error_manager
|
|
234
|
-
def
|
|
194
|
+
def find_url(
|
|
235
195
|
self,
|
|
236
|
-
|
|
237
|
-
tag: str = None,
|
|
238
|
-
notTag: str = None,
|
|
239
|
-
network: dto.Network = None,
|
|
240
|
-
language: dto.Language = None,
|
|
196
|
+
url: str,
|
|
241
197
|
page: int = 1,
|
|
242
198
|
lte: datetime = None,
|
|
243
199
|
gte: datetime = None,
|
|
244
|
-
) -> dto.
|
|
245
|
-
|
|
246
|
-
url = self._build_api_url__(
|
|
247
|
-
"fuzzy",
|
|
248
|
-
query,
|
|
249
|
-
tag=tag,
|
|
250
|
-
notTag=notTag,
|
|
251
|
-
network=network,
|
|
252
|
-
language=language,
|
|
253
|
-
page=page,
|
|
254
|
-
lte=lte,
|
|
255
|
-
gte=gte,
|
|
256
|
-
)
|
|
200
|
+
) -> dto.VysionResponse:
|
|
201
|
+
url = self._build_api_url__("document/url", url, page=page, lte=lte, gte=gte)
|
|
257
202
|
|
|
258
203
|
result = self._make_request(url)
|
|
259
204
|
return result.data
|
|
260
205
|
|
|
261
206
|
@vysion_error_manager
|
|
262
|
-
def
|
|
263
|
-
|
|
264
|
-
) -> dto.Result:
|
|
265
|
-
|
|
266
|
-
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)
|
|
267
209
|
|
|
268
210
|
result = self._make_request(url)
|
|
269
211
|
return result.data
|
|
270
212
|
|
|
271
213
|
@vysion_error_manager
|
|
272
|
-
def
|
|
273
|
-
self,
|
|
274
|
-
) -> dto.
|
|
275
|
-
|
|
276
|
-
|
|
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
|
+
)
|
|
277
220
|
|
|
278
221
|
result = self._make_request(url)
|
|
279
222
|
return result.data
|
|
280
223
|
|
|
281
224
|
@vysion_error_manager
|
|
282
|
-
def
|
|
283
|
-
self,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
)
|
|
287
236
|
|
|
288
237
|
result = self._make_request(url)
|
|
289
238
|
return result.data
|
|
290
239
|
|
|
291
240
|
@vysion_error_manager
|
|
292
|
-
def
|
|
293
|
-
|
|
294
|
-
|
|
241
|
+
def get_document_html(self, document_id: str) -> str:
|
|
242
|
+
url = self._build_api_url__("html", document_id)
|
|
243
|
+
|
|
244
|
+
result = requests.get(url)
|
|
295
245
|
|
|
296
|
-
|
|
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
|
+
)
|
|
297
275
|
|
|
298
276
|
result = self._make_request(url)
|
|
299
277
|
return result.data
|
|
300
278
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
) -> dto.Result:
|
|
279
|
+
#
|
|
280
|
+
# Ransomware Stats
|
|
281
|
+
#
|
|
305
282
|
|
|
306
|
-
|
|
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)
|
|
307
290
|
|
|
308
291
|
result = self._make_request(url)
|
|
309
292
|
return result.data
|
|
310
293
|
|
|
311
294
|
@vysion_error_manager
|
|
312
|
-
def
|
|
313
|
-
self,
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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)
|
|
317
301
|
|
|
318
302
|
result = self._make_request(url)
|
|
319
303
|
return result.data
|
|
320
304
|
|
|
321
|
-
# TODO find_domain?
|
|
322
305
|
@vysion_error_manager
|
|
323
|
-
def
|
|
306
|
+
def ransomware_attacks_stats(
|
|
324
307
|
self,
|
|
325
|
-
query_url: str,
|
|
326
|
-
page: int = 1,
|
|
327
|
-
lte: datetime = None,
|
|
328
308
|
gte: datetime = None,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
url = self._build_api_url__("
|
|
309
|
+
lte: datetime = None,
|
|
310
|
+
) -> dto.VysionResponse[dto.Stat]:
|
|
311
|
+
url = self._build_api_url__("stats/attacks", gte=gte, lte=lte)
|
|
332
312
|
|
|
333
313
|
result = self._make_request(url)
|
|
334
314
|
return result.data
|
|
335
315
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
) -> dto.Result:
|
|
316
|
+
#
|
|
317
|
+
# IM Search
|
|
318
|
+
#
|
|
340
319
|
|
|
341
|
-
|
|
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
|
+
)
|
|
342
338
|
|
|
343
339
|
result = self._make_request(url)
|
|
344
340
|
return result.data
|
|
345
341
|
|
|
346
342
|
@vysion_error_manager
|
|
347
|
-
def
|
|
348
|
-
|
|
349
|
-
|
|
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)
|
|
350
347
|
|
|
351
348
|
result = self._make_request(url)
|
|
352
349
|
return result.data
|
|
353
350
|
|
|
354
351
|
@vysion_error_manager
|
|
355
|
-
def
|
|
356
|
-
|
|
357
|
-
|
|
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)
|
|
358
356
|
|
|
359
357
|
result = self._make_request(url)
|
|
360
358
|
return result.data
|
|
361
|
-
|
|
362
|
-
@vysion_error_manager
|
|
363
|
-
def get_chat_telegram(
|
|
364
|
-
self,
|
|
365
|
-
channelId: str,
|
|
366
|
-
lte:datetime = None,
|
|
367
|
-
gte: datetime = None,
|
|
368
|
-
) -> dto.Result:
|
|
369
359
|
|
|
370
|
-
|
|
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)
|
|
371
365
|
|
|
372
366
|
result = self._make_request(url)
|
|
373
367
|
return result.data
|
|
374
|
-
|
|
375
|
-
@vysion_error_manager
|
|
376
|
-
def get_message_telegram(
|
|
377
|
-
self,
|
|
378
|
-
id: str,
|
|
379
|
-
) -> dto.Result:
|
|
380
368
|
|
|
381
|
-
|
|
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)
|
|
382
374
|
|
|
383
375
|
result = self._make_request(url)
|
|
384
376
|
return result.data
|
|
385
377
|
|
|
378
|
+
#
|
|
386
379
|
# FEEDS
|
|
380
|
+
#
|
|
381
|
+
|
|
387
382
|
@vysion_error_manager
|
|
388
383
|
def consume_feed_ransomware(self, batch_day: datetime = datetime.today()):
|
|
389
384
|
pass
|
|
@@ -403,7 +398,6 @@ class DaylyFeed(Client):
|
|
|
403
398
|
|
|
404
399
|
class RansomwareFeed(DaylyFeed):
|
|
405
400
|
def _consume_batch(self, start_time, end_time):
|
|
406
|
-
|
|
407
401
|
days = (datetime.now() - start_time).days
|
|
408
402
|
pages = (end_time - start_time).days
|
|
409
403
|
|
vysion/client/error.py
CHANGED
|
@@ -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
|
|
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
|
|
32
|
-
self.code =
|
|
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
|