1- import dataclasses
21import json
32from enum import Enum
4- from importlib .metadata import version
5- from typing import Any , cast
3+ from typing import Any
64
75import requests
86from l9format import l9format
9- from l9format .l9format import Model
107
11- from leakix .domain import L9Subdomain
12- from leakix .plugin import APIResult
8+ from leakix .base import BaseClient
9+ from leakix .base import HostResult as HostResult
1310from leakix .query import EmptyQuery , Query
1411from leakix .response import (
1512 AbstractResponse ,
@@ -24,32 +21,7 @@ class Scope(Enum):
2421 LEAK = "leak"
2522
2623
27- @dataclasses .dataclass
28- class HostResult (Model ):
29- Services : list [l9format .L9Event ] | None = None
30- Leaks : list [l9format .L9Event ] | None = None
31-
32-
33- DEFAULT_URL = "https://leakix.net"
34-
35-
36- class Client :
37- MAX_RESULTS_PER_PAGE = 20
38-
39- def __init__ (
40- self ,
41- api_key : str | None = None ,
42- base_url : str | None = DEFAULT_URL ,
43- ) -> None :
44- self .api_key = api_key
45- self .base_url = base_url if base_url else DEFAULT_URL
46- self .headers : dict [str , str ] = {
47- "Accept" : "application/json" ,
48- "User-agent" : f"leakix-client-python/{ version ('leakix' )} " ,
49- }
50- if api_key :
51- self .headers ["api-key" ] = api_key
52-
24+ class Client (BaseClient ):
5325 def __get (self , url : str , params : dict [str , Any ] | None ) -> AbstractResponse :
5426 r = requests .get (
5527 url ,
@@ -101,59 +73,34 @@ def get(
10173 else :
10274 serialized_query = " " .join (q .serialize () for q in queries )
10375 url = f"{ self .base_url } /search"
104- r = self .__get (
76+ return self .__get (
10577 url = url ,
10678 params = {
10779 "scope" : scope .value ,
10880 "q" : serialized_query ,
10981 "page" : page ,
11082 },
11183 )
112- return r
11384
11485 def get_service (
11586 self , queries : list [Query ] | None = None , page : int = 0
11687 ) -> AbstractResponse :
117- """
118- Shortcut for `get` with the scope `Scope.Service`.
119-
120- """
121- r = self .get (Scope .SERVICE , queries = queries , page = page )
122- if r .is_success ():
123- r .response_json = [
124- l9format .L9Event .from_dict (res ) for res in r .response_json
125- ]
126- return r
88+ """Shortcut for `get` with the scope `Scope.SERVICE`."""
89+ return self ._parse_events (self .get (Scope .SERVICE , queries = queries , page = page ))
12790
12891 def get_leak (
12992 self , queries : list [Query ] | None = None , page : int = 0
13093 ) -> AbstractResponse :
131- """
132- Shortcut for `get` with the scope `Scope.Leak`.
133- """
134- r = self .get (Scope .LEAK , queries = queries , page = page )
135- if r .is_success ():
136- r .response_json = [
137- l9format .L9Event .from_dict (res ) for res in r .response_json
138- ]
139- return r
94+ """Shortcut for `get` with the scope `Scope.LEAK`."""
95+ return self ._parse_events (self .get (Scope .LEAK , queries = queries , page = page ))
14096
14197 def get_host (self , ipv4 : str ) -> AbstractResponse :
14298 """
14399 Returns the list of services and associated leaks for a given host. Only the ipv4 format is supported at the
144100 moment.
145101 """
146102 url = f"{ self .base_url } /host/{ ipv4 } "
147- r = self .__get (url , params = None )
148- if r .is_success ():
149- response_json = r .json ()
150- formatted_result = cast (HostResult , HostResult .from_dict (response_json ))
151- response_json = {
152- "services" : formatted_result .Services ,
153- "leaks" : formatted_result .Leaks ,
154- }
155- r .response_json = response_json
156- return r
103+ return self ._parse_host_result (self .__get (url , params = None ))
157104
158105 def get_plugins (self ) -> AbstractResponse :
159106 """
@@ -166,10 +113,7 @@ def get_plugins(self) -> AbstractResponse:
166113 For the paid plans, have a look at https://leakix.net/plans.
167114 """
168115 url = f"{ self .base_url } /api/plugins"
169- r = self .__get (url , params = None )
170- if r .is_success ():
171- r .response_json = [APIResult .from_dict (d ) for d in r .json ()]
172- return r
116+ return self ._parse_plugins (self .__get (url , params = None ))
173117
174118 def get_subdomains (self , domain : str ) -> AbstractResponse :
175119 """
@@ -178,10 +122,7 @@ def get_subdomains(self, domain: str) -> AbstractResponse:
178122 To get back a JSON/Python dictionary, use the method `to_dict` on the individual element of the response object.
179123 """
180124 url = f"{ self .base_url } /api/subdomains/{ domain } "
181- r = self .__get (url , params = None )
182- if r .is_success ():
183- r .response_json = [L9Subdomain .from_dict (d ) for d in r .json ()]
184- return r
125+ return self ._parse_subdomains (self .__get (url , params = None ))
185126
186127 def bulk_export (self , queries : list [Query ] | None = None ) -> AbstractResponse :
187128 url = f"{ self .base_url } /bulk/search"
0 commit comments