pylookyloo 1.30.0__py3-none-any.whl → 1.31.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.
- pylookyloo/api.py +72 -11
- {pylookyloo-1.30.0.dist-info → pylookyloo-1.31.1.dist-info}/METADATA +3 -3
- pylookyloo-1.31.1.dist-info/RECORD +8 -0
- pylookyloo-1.30.0.dist-info/RECORD +0 -8
- {pylookyloo-1.30.0.dist-info → pylookyloo-1.31.1.dist-info}/LICENSE +0 -0
- {pylookyloo-1.30.0.dist-info → pylookyloo-1.31.1.dist-info}/WHEEL +0 -0
- {pylookyloo-1.30.0.dist-info → pylookyloo-1.31.1.dist-info}/entry_points.txt +0 -0
pylookyloo/api.py
CHANGED
|
@@ -7,6 +7,7 @@ import base64
|
|
|
7
7
|
import warnings
|
|
8
8
|
|
|
9
9
|
from datetime import datetime
|
|
10
|
+
from hashlib import sha512
|
|
10
11
|
from importlib.metadata import version
|
|
11
12
|
from io import BytesIO, StringIO
|
|
12
13
|
from typing import Any, TypedDict, overload, Literal
|
|
@@ -89,7 +90,7 @@ class CompareSettings(TypedDict, total=False):
|
|
|
89
90
|
class Lookyloo():
|
|
90
91
|
|
|
91
92
|
def __init__(self, root_url: str='https://lookyloo.circl.lu/', useragent: str | None=None,
|
|
92
|
-
*, proxies: dict[str, str] | None=None):
|
|
93
|
+
*, proxies: dict[str, str] | None=None, verify: bool | str=True) -> None:
|
|
93
94
|
'''Query a specific lookyloo instance.
|
|
94
95
|
|
|
95
96
|
:param root_url: URL of the instance to query.
|
|
@@ -109,6 +110,7 @@ class Lookyloo():
|
|
|
109
110
|
self.session.proxies.update(proxies)
|
|
110
111
|
retries = Retry(total=5, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504])
|
|
111
112
|
self.session.mount('http://', HTTPAdapter(max_retries=retries))
|
|
113
|
+
self.session.verify = verify
|
|
112
114
|
|
|
113
115
|
@property
|
|
114
116
|
def is_up(self) -> bool:
|
|
@@ -391,6 +393,14 @@ class Lookyloo():
|
|
|
391
393
|
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('admin', tree_uuid, 'remove'))))
|
|
392
394
|
return r.json()
|
|
393
395
|
|
|
396
|
+
def get_favicons(self, capture_uuid: str) -> dict[str, Any]:
|
|
397
|
+
'''Returns the potential favicons of the capture.
|
|
398
|
+
|
|
399
|
+
:param capture_uuid: UUID of the capture
|
|
400
|
+
'''
|
|
401
|
+
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('json', capture_uuid, 'favicons'))))
|
|
402
|
+
return r.json()
|
|
403
|
+
|
|
394
404
|
def get_redirects(self, capture_uuid: str) -> dict[str, Any]:
|
|
395
405
|
'''Returns the initial redirects.
|
|
396
406
|
|
|
@@ -415,6 +425,14 @@ class Lookyloo():
|
|
|
415
425
|
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('json', capture_uuid, 'hostnames'))))
|
|
416
426
|
return r.json()
|
|
417
427
|
|
|
428
|
+
def get_ips(self, capture_uuid: str) -> dict[str, Any]:
|
|
429
|
+
'''Returns all the IPs seen during the capture.
|
|
430
|
+
|
|
431
|
+
:param capture_uuid: UUID of the capture
|
|
432
|
+
'''
|
|
433
|
+
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('json', capture_uuid, 'ips'))))
|
|
434
|
+
return r.json()
|
|
435
|
+
|
|
418
436
|
def get_screenshot(self, capture_uuid: str) -> BytesIO:
|
|
419
437
|
'''Returns the screenshot.
|
|
420
438
|
|
|
@@ -475,35 +493,78 @@ class Lookyloo():
|
|
|
475
493
|
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('bin', capture_uuid, 'export'))))
|
|
476
494
|
return BytesIO(r.content)
|
|
477
495
|
|
|
478
|
-
def get_hash_occurrences(self, h: str) -> dict[str, Any]:
|
|
479
|
-
'''Returns the
|
|
496
|
+
def get_hash_occurrences(self, h: str, *, with_urls_occurrences: bool=False, cached_captures_only: bool=True, limit: int=20, offset: int=0) -> dict[str, Any]:
|
|
497
|
+
'''Returns the base64 body related the the hash, and a list of all the captures containing that hash.
|
|
480
498
|
|
|
481
499
|
:param h: sha512 to search
|
|
500
|
+
:param with_urls_occurrences: If true, add details about the URLs from the URL nodes in the tree.
|
|
501
|
+
:param cached_captures_only: If False, Lookyloo will attempt to re-cache the missing captures. It might take some time.
|
|
502
|
+
:param limit: The max amount of entries to return.
|
|
503
|
+
:param offset: The offset to start from, useful for pagination.
|
|
482
504
|
'''
|
|
483
|
-
r = self.session.
|
|
505
|
+
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('json', 'hash_info'))),
|
|
506
|
+
json={'body_hash': h, 'with_urls_occurrences': with_urls_occurrences,
|
|
507
|
+
'cached_captures_only': cached_captures_only, 'limit': limit, 'offset': offset})
|
|
484
508
|
return r.json()
|
|
485
509
|
|
|
486
|
-
def get_url_occurrences(self, url: str, limit: int=20,
|
|
510
|
+
def get_url_occurrences(self, url: str, *, with_urls_occurrences: bool=False, cached_captures_only: bool=True, limit: int=20, offset: int=0) -> dict[str, Any]:
|
|
487
511
|
'''Returns all the captures contining the URL
|
|
488
512
|
|
|
489
513
|
:param url: URL to lookup
|
|
490
|
-
:param
|
|
514
|
+
:param with_urls_occurrences: If true, add details about the URLs from the URL nodes in the tree.
|
|
491
515
|
:param cached_captures_only: If False, Lookyloo will attempt to re-cache the missing captures. It might take some time.
|
|
516
|
+
:param limit: The max amount of entries to return.
|
|
517
|
+
:param offset: The offset to start from, useful for pagination.
|
|
492
518
|
'''
|
|
493
519
|
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('json', 'url_info'))),
|
|
494
|
-
json={'url': url, '
|
|
520
|
+
json={'url': url, 'with_urls_occurrences': with_urls_occurrences,
|
|
521
|
+
'cached_captures_only': cached_captures_only,
|
|
522
|
+
'limit': limit, 'offset': offset})
|
|
495
523
|
return r.json()
|
|
496
524
|
|
|
497
|
-
def get_hostname_occurrences(self, hostname: str, with_urls_occurrences: bool=False, limit: int=20,
|
|
498
|
-
'''Returns all the captures contining the hostname.
|
|
525
|
+
def get_hostname_occurrences(self, hostname: str, *, with_urls_occurrences: bool=False, cached_captures_only: bool=True, limit: int=20, offset: int=0) -> dict[str, Any]:
|
|
526
|
+
'''Returns all the captures contining the hostname.
|
|
499
527
|
|
|
500
528
|
:param hostname: Hostname to lookup
|
|
501
529
|
:param with_urls_occurrences: If true, add details about the related URLs.
|
|
502
|
-
:param limit: The max amount of entries to return.
|
|
503
530
|
:param cached_captures_only: If False, Lookyloo will attempt to re-cache the missing captures. It might take some time.
|
|
531
|
+
:param limit: The max amount of entries to return.
|
|
532
|
+
:param offset: The offset to start from, useful for pagination.
|
|
504
533
|
'''
|
|
505
534
|
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('json', 'hostname_info'))),
|
|
506
|
-
json={'hostname': hostname, 'with_urls_occurrences': with_urls_occurrences,
|
|
535
|
+
json={'hostname': hostname, 'with_urls_occurrences': with_urls_occurrences,
|
|
536
|
+
'cached_captures_only': cached_captures_only,
|
|
537
|
+
'limit': limit, 'offset': offset})
|
|
538
|
+
return r.json()
|
|
539
|
+
|
|
540
|
+
def get_ip_occurrences(self, ip: str, *, with_urls_occurrences: bool=False, cached_captures_only: bool=True, limit: int=20, offset: int=0) -> dict[str, Any]:
|
|
541
|
+
'''Returns all the captures containing the IP address.
|
|
542
|
+
|
|
543
|
+
:param ip: IP to lookup
|
|
544
|
+
:param with_urls_occurrences: If true, add details about the related URLs.
|
|
545
|
+
:param cached_captures_only: If False, Lookyloo will attempt to re-cache the missing captures. It might take some time.
|
|
546
|
+
:param limit: The max amount of entries to return.
|
|
547
|
+
:param offset: The offset to start from, useful for pagination.
|
|
548
|
+
'''
|
|
549
|
+
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('json', 'ip_info'))),
|
|
550
|
+
json={'ip': ip, 'with_urls_occurrences': with_urls_occurrences,
|
|
551
|
+
'cached_captures_only': cached_captures_only,
|
|
552
|
+
'limit': limit})
|
|
553
|
+
return r.json()
|
|
554
|
+
|
|
555
|
+
def get_favicon_occurrences(self, favicon: str | BytesIO, *, cached_captures_only: bool=True, limit: int=20, offset: int=0) -> dict[str, Any]:
|
|
556
|
+
'''Returns all the captures containing the favicon.
|
|
557
|
+
|
|
558
|
+
:param favicon: Favicon to lookup. Either the hash, or the file in a BytesIO (hash will be generated on the fly)
|
|
559
|
+
:param cached_captures_only: If False, Lookyloo will attempt to re-cache the missing captures. It might take some time.
|
|
560
|
+
:param limit: The max amount of entries to return.
|
|
561
|
+
:param offset: The offset to start from, useful for pagination.
|
|
562
|
+
'''
|
|
563
|
+
if isinstance(favicon, BytesIO):
|
|
564
|
+
favicon = sha512(favicon.read()).hexdigest()
|
|
565
|
+
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('json', 'favicon_info'))),
|
|
566
|
+
json={'favicon': favicon, 'cached_captures_only': cached_captures_only,
|
|
567
|
+
'limit': limit, 'offset': offset})
|
|
507
568
|
return r.json()
|
|
508
569
|
|
|
509
570
|
def get_stats(self) -> dict[str, Any]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pylookyloo
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.31.1
|
|
4
4
|
Summary: Python CLI and module for Lookyloo
|
|
5
5
|
License: GPL-2.0-or-later
|
|
6
6
|
Author: Raphaël Vinot
|
|
@@ -24,8 +24,8 @@ Classifier: Topic :: Security
|
|
|
24
24
|
Provides-Extra: docs
|
|
25
25
|
Provides-Extra: examples
|
|
26
26
|
Requires-Dist: Sphinx (>=8.2.3) ; (python_version >= "3.11") and (extra == "docs")
|
|
27
|
-
Requires-Dist: pylacus (>=1.15.
|
|
28
|
-
Requires-Dist: requests (>=2.32.
|
|
27
|
+
Requires-Dist: pylacus (>=1.15.1) ; extra == "examples"
|
|
28
|
+
Requires-Dist: requests (>=2.32.4)
|
|
29
29
|
Project-URL: Documentation, https://pylookyloo.readthedocs.io/en/latest/
|
|
30
30
|
Project-URL: Repository, https://github.com/lookyloo/PyLookyloo
|
|
31
31
|
Project-URL: issues, https://github.com/lookyloo/PyLookyloo/issues
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pylookyloo/__init__.py,sha256=_JYXwXHL7ShZkeruvGd8qDTpxNRfuDjvV65SOMMU6yc,1922
|
|
2
|
+
pylookyloo/api.py,sha256=8k7ocTjcSOUE4F-NRC8XdbzXrXoOnhqLm2E_AOMmPzo,35853
|
|
3
|
+
pylookyloo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
pylookyloo-1.31.1.dist-info/LICENSE,sha256=4C4hLYrIkUD96Ggk-y_Go1Qf7PBZrEm9PSeTGe2nd4s,1516
|
|
5
|
+
pylookyloo-1.31.1.dist-info/METADATA,sha256=gLjS2G4hFwZvaqYpZGuUGwarr5D1b50kAS-OeXlR33c,2387
|
|
6
|
+
pylookyloo-1.31.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
7
|
+
pylookyloo-1.31.1.dist-info/entry_points.txt,sha256=y2c0Ujg8co6Xyf7MoxStVU-fLQMZBSGAg-KFidmsha4,44
|
|
8
|
+
pylookyloo-1.31.1.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pylookyloo/__init__.py,sha256=_JYXwXHL7ShZkeruvGd8qDTpxNRfuDjvV65SOMMU6yc,1922
|
|
2
|
-
pylookyloo/api.py,sha256=Udgl9O8R1IPzNCXfpP3zad7Y6Q0n2neVEWpAJQ58yHM,31907
|
|
3
|
-
pylookyloo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
pylookyloo-1.30.0.dist-info/LICENSE,sha256=4C4hLYrIkUD96Ggk-y_Go1Qf7PBZrEm9PSeTGe2nd4s,1516
|
|
5
|
-
pylookyloo-1.30.0.dist-info/METADATA,sha256=h1Rd0aoYA54mCmQyz6G719_DryKS2rF__543YPWlaJQ,2387
|
|
6
|
-
pylookyloo-1.30.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
7
|
-
pylookyloo-1.30.0.dist-info/entry_points.txt,sha256=y2c0Ujg8co6Xyf7MoxStVU-fLQMZBSGAg-KFidmsha4,44
|
|
8
|
-
pylookyloo-1.30.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|