|
1 | 1 | import json |
| 2 | +from collections.abc import Iterator |
2 | 3 | from enum import Enum |
3 | | -from typing import Any |
| 4 | +from typing import Any, cast |
4 | 5 |
|
5 | 6 | import requests |
6 | 7 | from l9format import l9format |
@@ -173,3 +174,48 @@ def bulk_service( |
173 | 174 | return SuccessResponse(response=r, response_json=[]) |
174 | 175 | else: |
175 | 176 | return ErrorResponse(response=r, response_json=r.json()) |
| 177 | + |
| 178 | + def get_domain(self, domain: str) -> AbstractResponse: |
| 179 | + """ |
| 180 | + Returns the list of services and associated leaks for a given domain. |
| 181 | + """ |
| 182 | + url = f"{self.base_url}/domain/{domain}" |
| 183 | + return self._parse_host_result(self.__get(url, params=None)) |
| 184 | + |
| 185 | + def search( |
| 186 | + self, query: str, scope: Scope = Scope.LEAK, page: int = 0 |
| 187 | + ) -> AbstractResponse: |
| 188 | + """ |
| 189 | + Simple search using a raw query string (same syntax as the website). |
| 190 | +
|
| 191 | + Example: |
| 192 | + >>> client.search("+plugin:GitConfigHttpPlugin", scope=Scope.LEAK) |
| 193 | + >>> client.search("+country:FR +port:22", scope=Scope.SERVICE) |
| 194 | + """ |
| 195 | + if page < 0: |
| 196 | + raise ValueError("Page argument must be a positive integer") |
| 197 | + url = f"{self.base_url}/search" |
| 198 | + r = self.__get( |
| 199 | + url=url, |
| 200 | + params={"scope": scope.value, "q": query, "page": page}, |
| 201 | + ) |
| 202 | + return self._parse_events(r) |
| 203 | + |
| 204 | + def bulk_export_stream( |
| 205 | + self, queries: list[AbstractQuery] | None = None |
| 206 | + ) -> Iterator[l9format.L9Aggregation]: |
| 207 | + """ |
| 208 | + Streaming version of bulk_export. Yields L9Aggregation objects one by one. |
| 209 | + More memory efficient for large result sets. |
| 210 | + """ |
| 211 | + url = f"{self.base_url}/bulk/search" |
| 212 | + params = {"q": serialize_queries(queries)} |
| 213 | + r = requests.get(url, params=params, headers=self.headers, stream=True) |
| 214 | + if r.status_code != 200: |
| 215 | + return |
| 216 | + for line in r.iter_lines(): |
| 217 | + json_event = json.loads(line) |
| 218 | + yield cast( |
| 219 | + l9format.L9Aggregation, |
| 220 | + l9format.L9Aggregation.from_dict(json_event), |
| 221 | + ) |
0 commit comments