vysion 2.1.7__tar.gz → 2.2.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: 2.1.7
3
+ Version: 2.2.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,7 +29,7 @@ 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: [2.1.7](https://pypi.org/project/vysion/)
32
+ Latest version: [2.2.0](https://pypi.org/project/vysion/)
33
33
 
34
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
 
@@ -4,7 +4,7 @@ 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: [2.1.7](https://pypi.org/project/vysion/)
7
+ Latest version: [2.2.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
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "vysion"
3
- version = "2.1.7"
3
+ version = "2.2.0"
4
4
  description = "The official Python client library for Vysion"
5
5
  homepage = "https://vysion.ai"
6
6
  repository = "https://github.com/ByronLabs/vysion-py"
@@ -25,18 +25,14 @@ softenum = "1.0.1"
25
25
  requests = "^2.28.1"
26
26
  pymisp = "^2.4.194"
27
27
 
28
- [tool.poetry.dev-dependencies]
29
- pytest = "7.1.2"
28
+ [tool.poetry.group.dev.dependencies]
29
+ pytest = "^8.3.2"
30
30
  python-dotenv = "0.19.2"
31
-
32
31
  flake8 = "4.0.1"
33
32
  pyflakes = "2.4.0"
34
33
  mypy = "^0.961"
35
34
  black = "^24.3.0"
36
-
37
- [tool.poetry.group.dev.dependencies]
38
35
  ruff = "^0.5.2"
39
- pytest = "^8.3.2"
40
36
 
41
37
  [build-system]
42
38
  requires = ["poetry-core>=1.0.0"]
@@ -38,6 +38,7 @@ from vysion.dto import (
38
38
  ImMessageHit,
39
39
  ImProfileHit,
40
40
  ImServerHit,
41
+ LeakHit,
41
42
  )
42
43
  from vysion.version import __version__ as vysion_version
43
44
 
@@ -556,6 +557,246 @@ class Client(BaseClient):
556
557
  return result.data
557
558
 
558
559
 
560
+ #
561
+ # Leak search methods
562
+ #
563
+
564
+ @vysion_error_manager
565
+ def get_leak_by_email(
566
+ self,
567
+ email: str,
568
+ page: int = 1,
569
+ page_size: int = 50,
570
+ gte: datetime = None,
571
+ lte: datetime = None,
572
+ ) -> VysionResponse[LeakHit]:
573
+ """
574
+ Search for leaks containing a specific email address.
575
+
576
+ :param email: Email address to search for
577
+ :param page: Page number (default: 1)
578
+ :param page_size: Results per page (default: 50, max: 100)
579
+ :param gte: Start date filter (optional)
580
+ :param lte: End date filter (optional)
581
+ :return: VysionResponse containing LeakHit objects
582
+ """
583
+ url = self._build_api_url__(
584
+ f"leak/email/{email}",
585
+ page=page,
586
+ page_size=page_size,
587
+ gte=gte,
588
+ lte=lte,
589
+ )
590
+
591
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
592
+ return result.data
593
+
594
+ @vysion_error_manager
595
+ def get_leak_by_wallet(
596
+ self,
597
+ chain: str,
598
+ address: str,
599
+ page: int = 1,
600
+ page_size: int = 50,
601
+ gte: datetime = None,
602
+ lte: datetime = None,
603
+ ) -> VysionResponse[LeakHit]:
604
+ """
605
+ Search for leaks containing a cryptocurrency wallet address.
606
+
607
+ :param chain: Blockchain (btc, eth, xmr, xrp, zec, dot, bnb, dash)
608
+ :param address: Wallet address
609
+ :param page: Page number (default: 1)
610
+ :param page_size: Results per page (default: 50, max: 100)
611
+ :param gte: Start date filter (optional)
612
+ :param lte: End date filter (optional)
613
+ :return: VysionResponse containing LeakHit objects
614
+ """
615
+ url = self._build_api_url__(
616
+ f"leak/wallet/{chain}/{address}",
617
+ page=page,
618
+ page_size=page_size,
619
+ gte=gte,
620
+ lte=lte,
621
+ )
622
+
623
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
624
+ return result.data
625
+
626
+ @vysion_error_manager
627
+ def get_leak_by_ip(
628
+ self,
629
+ ip_address: str,
630
+ page: int = 1,
631
+ page_size: int = 50,
632
+ gte: datetime = None,
633
+ lte: datetime = None,
634
+ ) -> VysionResponse[LeakHit]:
635
+ """
636
+ Search for leaks containing an IP address (IPv4 or IPv6).
637
+
638
+ :param ip_address: IP address to search for
639
+ :param page: Page number (default: 1)
640
+ :param page_size: Results per page (default: 50, max: 100)
641
+ :param gte: Start date filter (optional)
642
+ :param lte: End date filter (optional)
643
+ :return: VysionResponse containing LeakHit objects
644
+ """
645
+ url = self._build_api_url__(
646
+ f"leak/ip/{ip_address}",
647
+ page=page,
648
+ page_size=page_size,
649
+ gte=gte,
650
+ lte=lte,
651
+ )
652
+
653
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
654
+ return result.data
655
+
656
+ @vysion_error_manager
657
+ def get_leak_by_phone(
658
+ self,
659
+ country_code: str,
660
+ number: str,
661
+ page: int = 1,
662
+ page_size: int = 50,
663
+ gte: datetime = None,
664
+ lte: datetime = None,
665
+ ) -> VysionResponse[LeakHit]:
666
+ """
667
+ Search for leaks containing a phone number.
668
+
669
+ :param country_code: Country code (e.g., "1" for US, "34" for Spain)
670
+ :param number: Phone number without country code
671
+ :param page: Page number (default: 1)
672
+ :param page_size: Results per page (default: 50, max: 100)
673
+ :param gte: Start date filter (optional)
674
+ :param lte: End date filter (optional)
675
+ :return: VysionResponse containing LeakHit objects
676
+ """
677
+ url = self._build_api_url__(
678
+ f"leak/phone/{country_code}/{number}",
679
+ page=page,
680
+ page_size=page_size,
681
+ gte=gte,
682
+ lte=lte,
683
+ )
684
+
685
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
686
+ return result.data
687
+
688
+ @vysion_error_manager
689
+ def get_leak_by_username(
690
+ self,
691
+ username: str,
692
+ page: int = 1,
693
+ page_size: int = 50,
694
+ gte: datetime = None,
695
+ lte: datetime = None,
696
+ ) -> VysionResponse[LeakHit]:
697
+ """
698
+ Search for leaks containing a specific username.
699
+
700
+ :param username: Username to search for
701
+ :param page: Page number (default: 1)
702
+ :param page_size: Results per page (default: 50, max: 100)
703
+ :param gte: Start date filter (optional)
704
+ :param lte: End date filter (optional)
705
+ :return: VysionResponse containing LeakHit objects
706
+ """
707
+ url = self._build_api_url__(
708
+ f"leak/username/{username}",
709
+ page=page,
710
+ page_size=page_size,
711
+ gte=gte,
712
+ lte=lte,
713
+ )
714
+
715
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
716
+ return result.data
717
+
718
+ @vysion_error_manager
719
+ def get_leak_by_hash(
720
+ self,
721
+ hash_value: str,
722
+ page: int = 1,
723
+ page_size: int = 50,
724
+ gte: datetime = None,
725
+ lte: datetime = None,
726
+ ) -> VysionResponse[LeakHit]:
727
+ """
728
+ Search for leaks by file hash (SHA256, SHA1, or MD5).
729
+ Hash type is auto-detected based on length.
730
+
731
+ :param hash_value: File hash (32, 40, or 64 hex characters)
732
+ :param page: Page number (default: 1)
733
+ :param page_size: Results per page (default: 50, max: 100)
734
+ :param gte: Start date filter (optional)
735
+ :param lte: End date filter (optional)
736
+ :return: VysionResponse containing LeakHit objects
737
+ """
738
+ url = self._build_api_url__(
739
+ f"leak/hash/{hash_value}",
740
+ page=page,
741
+ page_size=page_size,
742
+ gte=gte,
743
+ lte=lte,
744
+ )
745
+
746
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
747
+ return result.data
748
+
749
+ @vysion_error_manager
750
+ def search_leaks(
751
+ self,
752
+ q: str,
753
+ page: int = 1,
754
+ page_size: int = 50,
755
+ gte: datetime = None,
756
+ lte: datetime = None,
757
+ ) -> VysionResponse[LeakHit]:
758
+ """
759
+ Generic search across all leak content and metadata fields.
760
+
761
+ :param q: Search query (minimum 3 characters)
762
+ :param page: Page number (default: 1)
763
+ :param page_size: Results per page (default: 50, max: 100)
764
+ :param gte: Start date filter (optional)
765
+ :param lte: End date filter (optional)
766
+ :return: VysionResponse containing LeakHit objects with highlights
767
+ """
768
+ url = self._build_api_url__(
769
+ "leak/search",
770
+ q=q,
771
+ page=page,
772
+ page_size=page_size,
773
+ gte=gte,
774
+ lte=lte,
775
+ )
776
+
777
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
778
+ return result.data
779
+
780
+ @vysion_error_manager
781
+ def get_leak_by_id(
782
+ self,
783
+ leak_id: str,
784
+ ) -> VysionResponse[LeakHit]:
785
+ """
786
+ Retrieve a single leak document by its Elasticsearch ID.
787
+ Includes downloadUrl if available from linked Telegram message.
788
+
789
+ :param leak_id: Elasticsearch document ID
790
+ :return: VysionResponse containing a single LeakHit object
791
+ """
792
+ url = self._build_api_url__(
793
+ f"leak/{leak_id}",
794
+ )
795
+
796
+ result = VysionResponse[LeakHit].model_validate(self._make_request(url))
797
+ return result.data
798
+
799
+
559
800
  #
560
801
  # FEEDS
561
802
  #
@@ -478,6 +478,57 @@ class ImServerHit(BaseModel):
478
478
  raise ValueError("creationDate field cannot be empty")
479
479
  return v
480
480
 
481
+ class LeakHit(BaseModel):
482
+ """
483
+ Represents a leak document from telegram-leaks-* indices.
484
+ Contains file metadata and detected sensitive information.
485
+ """
486
+ # Core identification
487
+ id: str
488
+ detectionDate: datetime
489
+
490
+ # File metadata
491
+ filePath: Optional[str] = Field(default_factory=lambda: None)
492
+ fileHash: Optional[str] = Field(default_factory=lambda: None) # SHA256, SHA1, or MD5
493
+ fileSize: Optional[int] = Field(default_factory=lambda: None)
494
+ fileType: Optional[str] = Field(default_factory=lambda: None)
495
+ detectedMimeType: Optional[str] = Field(default_factory=lambda: None)
496
+ decompressedFilename: Optional[str] = Field(default_factory=lambda: None)
497
+
498
+ # Archive metadata (if leak came from archive file)
499
+ archiveSource: Optional[str] = Field(default_factory=lambda: None)
500
+ archiveMemberPath: Optional[str] = Field(default_factory=lambda: None)
501
+
502
+ # Telegram source metadata
503
+ telegram: Optional[dict] = Field(default_factory=lambda: None) # Contains channel_id, message_id, etc.
504
+
505
+ # Detected sensitive information (enrichment data)
506
+ detectedInfo: Optional[dict] = Field(default_factory=lambda: None)
507
+ # detectedInfo contains: emails, usernames, phone_numbers, ipv4_addresses, ipv6_addresses,
508
+ # btc_wallets, eth_wallets, xmr_wallets, xrp_wallets, zec_wallets, dot_wallets, bnb_wallets, dash_wallets
509
+
510
+ # Language detection
511
+ language: Optional[str] = Field(default_factory=lambda: None)
512
+ languages: Optional[List[LanguagePair]] = Field(default_factory=lambda: None)
513
+
514
+ # Parse status
515
+ parseStatus: Optional[str] = Field(default_factory=lambda: None)
516
+
517
+ # Download URL (only present for /leak/{id} endpoint)
518
+ downloadUrl: Optional[str] = Field(default_factory=lambda: None)
519
+
520
+ # Search highlights (only present for search endpoints)
521
+ highlight: Optional[dict] = Field(default_factory=lambda: None)
522
+
523
+ model_config = ConfigDict(exclude_defaults=True)
524
+
525
+ @field_validator("detectionDate")
526
+ def validate_detectionDate(cls, v: datetime) -> datetime:
527
+ if not v:
528
+ raise ValueError("detectionDate field cannot be empty")
529
+ return v
530
+
531
+
481
532
  class ImFeedHit(BaseModel):
482
533
  id: str
483
534
  telegram: List[str]
@@ -15,4 +15,4 @@ See the License for the specific language governing permissions and
15
15
  limitations under the License.
16
16
  """
17
17
 
18
- __version__ = "2.1.7"
18
+ __version__ = "2.2.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes