Skip to content

Commit 0b1e853

Browse files
authored
Merge pull request #1 from LeakIX/add-plugins
Add plugins
2 parents 147a27c + cb895db commit 0b1e853

6 files changed

Lines changed: 57 additions & 36 deletions

File tree

example/example_client.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77

88
API_KEY = decouple.config("API_KEY")
9-
CLIENT = Client(api_key=API_KEY)
9+
BASE_URL = decouple.config("LEAKIX_HOST", default=None)
10+
CLIENT = Client(api_key=API_KEY, base_url=BASE_URL)
1011

1112

1213
def example_get_host_filter_plugin():
@@ -65,9 +66,17 @@ def example_get_leak_raw_query():
6566
)
6667

6768

69+
def example_get_plugins():
70+
response = CLIENT.get_plugins()
71+
for p in response.json():
72+
print(p.name)
73+
print(p.description)
74+
75+
6876
if __name__ == "__main__":
6977
example_get_host_filter_plugin()
7078
example_get_service_filter_plugin()
7179
example_get_leaks_filter_multiple_plugins()
7280
example_get_leaks_multiple_filter_plugins_must_not()
7381
example_get_leak_raw_query()
82+
example_get_plugins()

leakix/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33
from leakix.plugin import *
44
from leakix.query import *
55
from leakix.response import *
6-
7-
__VERSION__ = "0.1.2"
6+
from leakix.client import __VERSION__

leakix/client.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
import os
33
from typing import Optional, List
44
import requests
5-
from pprint import pprint
65
from l9format import l9format
76
from enum import Enum
87
from serde import Model, fields
98
from leakix.response import SuccessResponse, ErrorResponse, RateLimitResponse
109
from leakix.query import *
1110
from leakix.plugin import *
1211
from leakix.field import *
13-
from leakix import __VERSION__
12+
13+
14+
__VERSION__ = "0.1.2"
1415

1516

1617
class Scope(Enum):
@@ -24,28 +25,24 @@ class HostResult(Model):
2425

2526

2627
class Client:
27-
BASE_URL = "https://leakix.net"
28-
29-
def __init__(self, api_key: Optional[str] = None):
28+
def __init__(
29+
self,
30+
api_key: Optional[str] = None,
31+
base_url: Optional[str] = "https://leakix.net",
32+
):
3033
self.api_key = api_key
34+
self.base_url = base_url
3135
self.headers = {
3236
"Accept": "application/json",
3337
"User-agent": "leakix-client-python/%s" % __VERSION__,
3438
}
3539
if api_key:
3640
self.headers["api-key"] = api_key
3741

38-
def get(self, scope: Scope, queries: Optional[List[Query]] = None):
39-
if queries is None or len(queries) == 0:
40-
serialized_query = EmptyQuery().serialize()
41-
else:
42-
serialized_query = [q.serialize() for q in queries]
43-
serialized_query = " ".join(serialized_query)
44-
serialized_query = "%s" % serialized_query
45-
url = "%s/search" % self.BASE_URL
42+
def __get(self, url, params):
4643
r = requests.get(
4744
url,
48-
params={"scope": scope.value, "q": serialized_query},
45+
params=params,
4946
headers=self.headers,
5047
)
5148
if r.status_code == 200:
@@ -54,7 +51,18 @@ def get(self, scope: Scope, queries: Optional[List[Query]] = None):
5451
elif r.status_code == 429:
5552
return RateLimitResponse(response=r)
5653
else:
57-
return ErrorResponse(response=r, response_json=response.json())
54+
return ErrorResponse(response=r, response_json=r.json())
55+
56+
def get(self, scope: Scope, queries: Optional[List[Query]] = None):
57+
if queries is None or len(queries) == 0:
58+
serialized_query = EmptyQuery().serialize()
59+
else:
60+
serialized_query = [q.serialize() for q in queries]
61+
serialized_query = " ".join(serialized_query)
62+
serialized_query = "%s" % serialized_query
63+
url = "%s/search" % self.base_url
64+
r = self.__get(url=url, params={"scope": scope.value, "q": serialized_query})
65+
return r
5866

5967
def get_service(self, queries: Optional[List[Query]] = None):
6068
r = self.get(Scope.SERVICE, queries=queries)
@@ -73,18 +81,21 @@ def get_leak(self, queries: Optional[List[Query]] = None):
7381
return r
7482

7583
def get_host(self, ipv4: str):
76-
url = "%s/host/%s" % (self.BASE_URL, ipv4)
77-
r = requests.get(url, headers=self.headers)
78-
if r.status_code == 200:
84+
url = "%s/host/%s" % (self.base_url, ipv4)
85+
r = self.__get(url, params=None)
86+
if r.is_success():
7987
response_json = r.json()
8088
formatted_result = HostResult.from_dict(response_json)
8189
response_json = {
8290
"services": formatted_result.Services,
8391
"leaks": formatted_result.Leaks,
8492
}
85-
return SuccessResponse(response=r, response_json=response_json)
86-
elif r.status_code == 429:
87-
return RateLimitResponse(response=r)
88-
else:
89-
response_json = r.json()
90-
return ErrorResponse(response=r, response_json=response_json)
93+
r.response_json = response_json
94+
return r
95+
96+
def get_plugins(self):
97+
url = "%s/api/plugins" % (self.base_url)
98+
r = self.__get(url, params=None)
99+
if r.is_success():
100+
r.response_json = [APIResult.from_dict(d) for d in r.json()]
101+
return r

leakix/plugin.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
from enum import Enum
2+
from serde import Model, fields
3+
4+
5+
class APIResult(Model):
6+
name: fields.Str()
7+
description: fields.Str()
28

39

410
class Plugin(Enum):

leakix/response.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44
class AbstractResponse(metaclass=ABCMeta):
55
def __init__(self, response, response_json=None):
66
self.response = response
7-
self.response_json = response_json
7+
self.response_json = response_json or response.json()
88

99
def json(self):
10-
return (
11-
self.response_json
12-
if self.response_json is not None
13-
else self.response.json()
14-
)
10+
return self.response_json
1511

1612
def status_code(self):
1713
return self.response.status_code

tests/test_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_get_host_success(client):
3030
# remove .json
3131
ipv4 = f.name[:-5]
3232
with requests_mock.Mocker() as m:
33-
url = "%s/host/%s" % (client.BASE_URL, ipv4)
33+
url = "%s/host/%s" % (client.base_url, ipv4)
3434
m.get(url, json=res_json, status_code=200)
3535
response = client.get_host(ipv4)
3636
assert response.is_success()
@@ -47,7 +47,7 @@ def test_get_host_404(client):
4747
ipv4 = f.name[:-5]
4848
client = Client()
4949
with requests_mock.Mocker() as m:
50-
url = "%s/host/%s" % (client.BASE_URL, ipv4)
50+
url = "%s/host/%s" % (client.base_url, ipv4)
5151
m.get(url, json=res_json, status_code=404)
5252
response = client.get_host(ipv4)
5353
assert response.is_error()
@@ -60,7 +60,7 @@ def test_get_host_429(client, fake_ipv4):
6060
status_code = 429
6161
res_json = {"reason": "rate-limit", "status": "error"}
6262
with requests_mock.Mocker() as m:
63-
url = "%s/host/%s" % (client.BASE_URL, fake_ipv4)
63+
url = "%s/host/%s" % (client.base_url, fake_ipv4)
6464
m.get(url, json=res_json, status_code=status_code)
6565
response = client.get_host(fake_ipv4)
6666
assert response.is_error()

0 commit comments

Comments
 (0)