vysion 2.0.19__tar.gz → 2.1.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.
- {vysion-2.0.19 → vysion-2.1.0}/PKG-INFO +5 -6
- {vysion-2.0.19 → vysion-2.1.0}/README.md +2 -2
- {vysion-2.0.19 → vysion-2.1.0}/pyproject.toml +1 -1
- {vysion-2.0.19 → vysion-2.1.0}/vysion/client/client.py +49 -7
- {vysion-2.0.19 → vysion-2.1.0}/vysion/dto/dto.py +93 -1
- {vysion-2.0.19 → vysion-2.1.0}/vysion/dto/util.py +1 -1
- {vysion-2.0.19 → vysion-2.1.0}/vysion/version.py +1 -1
- {vysion-2.0.19 → vysion-2.1.0}/LICENSE +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/client/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/client/error.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/dto/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/dto/tag.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/enum/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/enum/languages.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/enum/networks.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/enum/ransom_groups.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/model/enum/services.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/taxonomy/__init__.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/taxonomy/flavours.py +0 -0
- {vysion-2.0.19 → vysion-2.1.0}/vysion/taxonomy/taxonomy.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: vysion
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: The official Python client library for Vysion
|
|
5
|
+
Home-page: https://vysion.ai
|
|
5
6
|
License: Apache-2.0
|
|
6
7
|
Author: Javier Junquera-Sánchez
|
|
7
8
|
Author-email: javier.junquera@byronlabs.io
|
|
@@ -14,23 +15,21 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Requires-Dist: pydantic (>=2.0.1,<3.0.0)
|
|
19
19
|
Requires-Dist: pymisp (>=2.4.194,<3.0.0)
|
|
20
20
|
Requires-Dist: requests (>=2.28.1,<3.0.0)
|
|
21
21
|
Requires-Dist: softenum (==1.0.1)
|
|
22
22
|
Project-URL: Documentation, https://developers.vysion.ai
|
|
23
|
-
Project-URL: Homepage, https://vysion.ai
|
|
24
23
|
Project-URL: Repository, https://github.com/ByronLabs/vysion-py
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
|
|
27
26
|
# Vysion-PY
|
|
28
27
|
|
|
29
|
-
Welcome to the
|
|
28
|
+
Welcome to the PyPi webpage for Vysion, our implementation as a Python library to use the Vysion tool. Vysion is a dark web intelligence tool that provides information collected from web pages from Tor, I2P, cybercrime forums on the clearnet, etc. Vysion API also provides a feed of information on ransomware attacks published by the various ransomware groups currently active.
|
|
30
29
|
|
|
31
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).
|
|
32
31
|
|
|
33
|
-
Latest version: [2.0
|
|
32
|
+
Latest version: [2.1.0](https://pypi.org/project/vysion/)
|
|
34
33
|
|
|
35
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.
|
|
36
35
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Vysion-PY
|
|
2
2
|
|
|
3
|
-
Welcome to the
|
|
3
|
+
Welcome to the PyPi webpage for Vysion, our implementation as a Python library to use the Vysion tool. Vysion is a dark web intelligence tool that provides information collected from web pages from Tor, I2P, cybercrime forums on the clearnet, etc. Vysion API also provides a feed of information on ransomware attacks published by the various ransomware groups currently active.
|
|
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: [2.0
|
|
7
|
+
Latest version: [2.1.0](https://pypi.org/project/vysion/)
|
|
8
8
|
|
|
9
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
|
|
|
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
# TODO Referenciar vt-py
|
|
19
|
-
|
|
20
18
|
import logging
|
|
21
19
|
import os
|
|
22
20
|
from datetime import datetime, timedelta
|
|
@@ -323,7 +321,7 @@ class Client(BaseClient):
|
|
|
323
321
|
@vysion_error_manager
|
|
324
322
|
def search_ransomware_victim(
|
|
325
323
|
self,
|
|
326
|
-
q: str,
|
|
324
|
+
q: str = None,
|
|
327
325
|
lte: datetime = None,
|
|
328
326
|
gte: datetime = None,
|
|
329
327
|
page: int = 1,
|
|
@@ -419,6 +417,51 @@ class Client(BaseClient):
|
|
|
419
417
|
result = VysionResponse[ImMessageHit].model_validate(self._make_request(url))
|
|
420
418
|
return result.data
|
|
421
419
|
|
|
420
|
+
|
|
421
|
+
@vysion_error_manager
|
|
422
|
+
def im_find_email(
|
|
423
|
+
self,
|
|
424
|
+
email: str,
|
|
425
|
+
page: int = 1,
|
|
426
|
+
page_size: int = 10,
|
|
427
|
+
lte: datetime = None,
|
|
428
|
+
gte: datetime = None
|
|
429
|
+
) -> VysionResponse[DocumentHit]:
|
|
430
|
+
url = self._build_api_url__(
|
|
431
|
+
"im/email",
|
|
432
|
+
email,
|
|
433
|
+
page=page,
|
|
434
|
+
page_size=page_size,
|
|
435
|
+
lte=lte,
|
|
436
|
+
gte=gte
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
result = VysionResponse[ImProfileHit].model_validate(self._make_request(url))
|
|
440
|
+
return result.data
|
|
441
|
+
|
|
442
|
+
@vysion_error_manager
|
|
443
|
+
def im_find_wallet(
|
|
444
|
+
self,
|
|
445
|
+
chain: str,
|
|
446
|
+
address: str,
|
|
447
|
+
page: int = 1,
|
|
448
|
+
page_size: int = 10,
|
|
449
|
+
lte: datetime = None,
|
|
450
|
+
gte: datetime = None,
|
|
451
|
+
) -> VysionResponse[DocumentHit]:
|
|
452
|
+
url = self._build_api_url__(
|
|
453
|
+
"im/wallet/" + chain,
|
|
454
|
+
address,
|
|
455
|
+
page=page,
|
|
456
|
+
page_size=page_size,
|
|
457
|
+
lte=lte,
|
|
458
|
+
gte=gte
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
result = VysionResponse[ImProfileHit].model_validate(self._make_request(url))
|
|
462
|
+
return result.data
|
|
463
|
+
|
|
464
|
+
|
|
422
465
|
@vysion_error_manager
|
|
423
466
|
def get_im_chat(
|
|
424
467
|
self, platform: str, channelId: str, gte: datetime = None, lte: datetime = None
|
|
@@ -465,6 +508,7 @@ class Client(BaseClient):
|
|
|
465
508
|
|
|
466
509
|
result = VysionResponse[ImServerHit].model_validate(self._make_request(url))
|
|
467
510
|
return result.data
|
|
511
|
+
|
|
468
512
|
|
|
469
513
|
#
|
|
470
514
|
# FEEDS
|
|
@@ -472,6 +516,7 @@ class Client(BaseClient):
|
|
|
472
516
|
|
|
473
517
|
@vysion_error_manager
|
|
474
518
|
def consume_feed_ransomware(self, batch_day: datetime = datetime.today()):
|
|
519
|
+
#TODO implement client feed logic
|
|
475
520
|
pass
|
|
476
521
|
|
|
477
522
|
|
|
@@ -494,7 +539,4 @@ class RansomwareFeed(DaylyFeed):
|
|
|
494
539
|
|
|
495
540
|
for page in range(pages):
|
|
496
541
|
url = self._build_api_url__("feed", "ransomware", days=days, page=page + 1)
|
|
497
|
-
yield self._make_request(url)
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
# TODO /api/v1/feeds
|
|
542
|
+
yield self._make_request(url)
|
|
@@ -303,7 +303,25 @@ class ImMessageHit(BaseModel):
|
|
|
303
303
|
detectionDate: datetime
|
|
304
304
|
serverId: Optional[Union[int, str]] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
305
305
|
serverTitle: Optional[str] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
306
|
-
platform: Optional[str] = Field(default_factory=lambda: None)
|
|
306
|
+
platform: Optional[str] = Field(default_factory=lambda: None)
|
|
307
|
+
|
|
308
|
+
@model_validator(mode="after")
|
|
309
|
+
def validate_platform_specific_fields(cls, values):
|
|
310
|
+
"""
|
|
311
|
+
Conditionally include platform-specific fields:
|
|
312
|
+
- Include Discord-specific fields only for Discord platform
|
|
313
|
+
- Exclude Discord-specific fields for Telegram platform
|
|
314
|
+
"""
|
|
315
|
+
platform = getattr(values, "platform", None)
|
|
316
|
+
|
|
317
|
+
# For Telegram platform, remove Discord-specific fields
|
|
318
|
+
if platform is None or (isinstance(platform, str) and platform.lower() == "telegram"):
|
|
319
|
+
# Delete attributes instead of setting to None
|
|
320
|
+
for attr in ["serverId", "serverTitle"]:
|
|
321
|
+
if hasattr(values, attr):
|
|
322
|
+
delattr(values, attr)
|
|
323
|
+
|
|
324
|
+
return values
|
|
307
325
|
|
|
308
326
|
class ImMessageCardHit(BaseModel):
|
|
309
327
|
userId: Optional[Union[int, str]] = Field(default_factory=lambda: None)
|
|
@@ -318,6 +336,24 @@ class ImMessageCardHit(BaseModel):
|
|
|
318
336
|
serverTitle: Optional[str] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
319
337
|
platform: Optional[str] = Field(default_factory=lambda: None)
|
|
320
338
|
|
|
339
|
+
@model_validator(mode="after")
|
|
340
|
+
def validate_platform_specific_fields(cls, values):
|
|
341
|
+
"""
|
|
342
|
+
Conditionally include platform-specific fields:
|
|
343
|
+
- Include Discord-specific fields only for Discord platform
|
|
344
|
+
- Exclude Discord-specific fields for Telegram platform
|
|
345
|
+
"""
|
|
346
|
+
platform = getattr(values, "platform", None)
|
|
347
|
+
|
|
348
|
+
# For Telegram platform, remove Discord-specific fields
|
|
349
|
+
if platform is None or (isinstance(platform, str) and platform.lower() == "telegram"):
|
|
350
|
+
# Delete attributes instead of setting to None
|
|
351
|
+
for attr in ["serverId", "serverTitle"]:
|
|
352
|
+
if hasattr(values, attr):
|
|
353
|
+
delattr(values, attr)
|
|
354
|
+
|
|
355
|
+
return values
|
|
356
|
+
|
|
321
357
|
class ImProfileHit(BaseModel):
|
|
322
358
|
userId: Union[int, str]
|
|
323
359
|
usernames: Optional[List[str]] = Field(default_factory=lambda: None)
|
|
@@ -328,8 +364,41 @@ class ImProfileHit(BaseModel):
|
|
|
328
364
|
bot: Optional[bool] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
329
365
|
discordLink: Optional[List[str]] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
330
366
|
discriminator: Optional[List[int]] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
367
|
+
# TODO platform should be mandatory
|
|
331
368
|
platform: Optional[str] = Field(default_factory=lambda: None)
|
|
369
|
+
email: List[Email] = Field(default_factory=lambda: [])
|
|
370
|
+
paste: List[Paste] = Field(default_factory=lambda: [])
|
|
371
|
+
skype: List[Skype] = Field(default_factory=lambda: [])
|
|
372
|
+
telegram: List[Telegram] = Field(default_factory=lambda: [])
|
|
373
|
+
whatsapp: List[WhatsApp] = Field(default_factory=lambda: [])
|
|
374
|
+
bitcoin_address: List[BitcoinAddress] = Field(default_factory=lambda: [])
|
|
375
|
+
polkadot_address: List[PolkadotAddress] = Field(default_factory=lambda: [])
|
|
376
|
+
ethereum_address: List[EthereumAddress] = Field(default_factory=lambda: [])
|
|
377
|
+
monero_address: List[MoneroAddress] = Field(default_factory=lambda: [])
|
|
378
|
+
ripple_address: List[RippleAddress] = Field(default_factory=lambda: [])
|
|
379
|
+
zcash_address: List[ZcashAddress] = Field(default_factory=lambda: [])
|
|
380
|
+
|
|
332
381
|
|
|
382
|
+
model_config = ConfigDict(exclude_defaults=True)
|
|
383
|
+
|
|
384
|
+
@model_validator(mode="after")
|
|
385
|
+
def validate_platform_specific_fields(cls, values):
|
|
386
|
+
"""
|
|
387
|
+
Conditionally include platform-specific fields:
|
|
388
|
+
- Include Discord-specific fields only for Discord platform
|
|
389
|
+
- Exclude Discord-specific fields for Telegram platform
|
|
390
|
+
"""
|
|
391
|
+
platform = getattr(values, "platform", None)
|
|
392
|
+
|
|
393
|
+
# For Telegram platform, remove Discord-specific fields
|
|
394
|
+
if platform is None or (isinstance(platform, str) and platform.lower() == "telegram"):
|
|
395
|
+
# Delete attributes instead of setting to None
|
|
396
|
+
for attr in ["discordLink", "bot", "discriminator"]:
|
|
397
|
+
if hasattr(values, attr):
|
|
398
|
+
delattr(values, attr)
|
|
399
|
+
|
|
400
|
+
return values
|
|
401
|
+
|
|
333
402
|
@field_validator("userId")
|
|
334
403
|
def validate_userId(cls, v: int) -> int:
|
|
335
404
|
if not v:
|
|
@@ -353,6 +422,29 @@ class ImChannelHit(BaseModel):
|
|
|
353
422
|
serverTitle: Optional[List[str]] = Field(default_factory=lambda: None) #Discord Exclusive
|
|
354
423
|
platform: Optional[str] = Field(default_factory=lambda: None)
|
|
355
424
|
|
|
425
|
+
@model_validator(mode="after")
|
|
426
|
+
def validate_platform_specific_fields(cls, values):
|
|
427
|
+
"""
|
|
428
|
+
Conditionally include platform-specific fields:
|
|
429
|
+
- Include Discord-specific fields only for Discord platform
|
|
430
|
+
- Exclude Discord-specific fields for Telegram platform
|
|
431
|
+
"""
|
|
432
|
+
platform = getattr(values, "platform", None)
|
|
433
|
+
|
|
434
|
+
# For Telegram platform, remove Discord-specific fields
|
|
435
|
+
if platform is None or (isinstance(platform, str) and platform.lower() == "telegram"):
|
|
436
|
+
# Delete attributes instead of setting to None
|
|
437
|
+
for attr in ["serverId", "serverTitle"]:
|
|
438
|
+
if hasattr(values, attr):
|
|
439
|
+
delattr(values, attr)
|
|
440
|
+
else:
|
|
441
|
+
# For Discord platform, remove Telegram-specific fields
|
|
442
|
+
for attr in ["channelPhoto"]:
|
|
443
|
+
if hasattr(values, attr):
|
|
444
|
+
delattr(values, attr)
|
|
445
|
+
|
|
446
|
+
return values
|
|
447
|
+
|
|
356
448
|
@field_validator("detectionDate")
|
|
357
449
|
def validate_detectionDate(cls, v: datetime) -> datetime:
|
|
358
450
|
if not v:
|
|
@@ -79,7 +79,7 @@ class MISPProcessor:
|
|
|
79
79
|
self.misp_event.add_attribute("xmr", value=xmr.value)
|
|
80
80
|
|
|
81
81
|
for xrp in hit.ripple_address:
|
|
82
|
-
self.misp_event.add_attribute("xrp", value=
|
|
82
|
+
self.misp_event.add_attribute("xrp", value=xrp.value)
|
|
83
83
|
|
|
84
84
|
for zec in hit.zcash_address:
|
|
85
85
|
self.misp_event.add_attribute("zec", value=zec.value)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|