diff --git a/.gitignore b/.gitignore index 459ca99..18b33f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,38 +1 @@ -``` -# Compiled Python files -*.pyc -__pycache__/ - -# Dependencies -.venv/ -venv/ -.env -.env.local -*.env.* - -# Logs -*.log - -# Coverage reports -.coverage -coverage/ -htmlcov/ - -# IDE files -.vscode/ -.idea/ -*.swp -*.swo -*.tmp - -# OS files -.DS_Store -Thumbs.db - -# Build artifacts -dist/ -build/ -target/ -.mypy_cache/ -.pytest_cache/ -``` \ No newline at end of file +(src/netsleuth/ip_geo.py) \ No newline at end of file diff --git a/src/netsleuth/__pycache__/__init__.cpython-314.pyc b/src/netsleuth/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..15c73ae Binary files /dev/null and b/src/netsleuth/__pycache__/__init__.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/bgp.cpython-314.pyc b/src/netsleuth/__pycache__/bgp.cpython-314.pyc new file mode 100644 index 0000000..e51871d Binary files /dev/null and b/src/netsleuth/__pycache__/bgp.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/cli.cpython-314.pyc b/src/netsleuth/__pycache__/cli.cpython-314.pyc new file mode 100644 index 0000000..527623a Binary files /dev/null and b/src/netsleuth/__pycache__/cli.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/compare.cpython-314.pyc b/src/netsleuth/__pycache__/compare.cpython-314.pyc new file mode 100644 index 0000000..be4c4f6 Binary files /dev/null and b/src/netsleuth/__pycache__/compare.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/config.cpython-314.pyc b/src/netsleuth/__pycache__/config.cpython-314.pyc new file mode 100644 index 0000000..e614424 Binary files /dev/null and b/src/netsleuth/__pycache__/config.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/exporter.cpython-314.pyc b/src/netsleuth/__pycache__/exporter.cpython-314.pyc new file mode 100644 index 0000000..9f3c1c3 Binary files /dev/null and b/src/netsleuth/__pycache__/exporter.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/iface.cpython-314.pyc b/src/netsleuth/__pycache__/iface.cpython-314.pyc new file mode 100644 index 0000000..000cf45 Binary files /dev/null and b/src/netsleuth/__pycache__/iface.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/interpret.cpython-314.pyc b/src/netsleuth/__pycache__/interpret.cpython-314.pyc new file mode 100644 index 0000000..29e1436 Binary files /dev/null and b/src/netsleuth/__pycache__/interpret.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/ip_geo.cpython-314.pyc b/src/netsleuth/__pycache__/ip_geo.cpython-314.pyc new file mode 100644 index 0000000..1bb2fcc Binary files /dev/null and b/src/netsleuth/__pycache__/ip_geo.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/models.cpython-314.pyc b/src/netsleuth/__pycache__/models.cpython-314.pyc new file mode 100644 index 0000000..487e864 Binary files /dev/null and b/src/netsleuth/__pycache__/models.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/netinfo.cpython-314.pyc b/src/netsleuth/__pycache__/netinfo.cpython-314.pyc new file mode 100644 index 0000000..46d98ba Binary files /dev/null and b/src/netsleuth/__pycache__/netinfo.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/orchestration.cpython-314.pyc b/src/netsleuth/__pycache__/orchestration.cpython-314.pyc new file mode 100644 index 0000000..6feb4b8 Binary files /dev/null and b/src/netsleuth/__pycache__/orchestration.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/reputation.cpython-314.pyc b/src/netsleuth/__pycache__/reputation.cpython-314.pyc new file mode 100644 index 0000000..9386fe5 Binary files /dev/null and b/src/netsleuth/__pycache__/reputation.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/speed.cpython-314.pyc b/src/netsleuth/__pycache__/speed.cpython-314.pyc new file mode 100644 index 0000000..d5cfe39 Binary files /dev/null and b/src/netsleuth/__pycache__/speed.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/stats.cpython-314.pyc b/src/netsleuth/__pycache__/stats.cpython-314.pyc new file mode 100644 index 0000000..dc16735 Binary files /dev/null and b/src/netsleuth/__pycache__/stats.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/traceparse.cpython-314.pyc b/src/netsleuth/__pycache__/traceparse.cpython-314.pyc new file mode 100644 index 0000000..02b3da4 Binary files /dev/null and b/src/netsleuth/__pycache__/traceparse.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/validator.cpython-314.pyc b/src/netsleuth/__pycache__/validator.cpython-314.pyc new file mode 100644 index 0000000..897d406 Binary files /dev/null and b/src/netsleuth/__pycache__/validator.cpython-314.pyc differ diff --git a/src/netsleuth/__pycache__/watch.cpython-314.pyc b/src/netsleuth/__pycache__/watch.cpython-314.pyc new file mode 100644 index 0000000..d23c3fc Binary files /dev/null and b/src/netsleuth/__pycache__/watch.cpython-314.pyc differ diff --git a/src/netsleuth/ip_geo.py b/src/netsleuth/ip_geo.py index f155c50..bb2a93f 100644 --- a/src/netsleuth/ip_geo.py +++ b/src/netsleuth/ip_geo.py @@ -2,14 +2,70 @@ from __future__ import annotations import asyncio from dataclasses import fields as dataclass_fields +from functools import lru_cache import ipaddress import re +import time import httpx from netsleuth.config import Providers from netsleuth.models import CfTrace, IpGeo + +# Кэш для API запросов (ключ: url+час, значение: ответ) +# Инвалидируется автоматически каждый час благодаря timestamp_hour +_API_CACHE: dict[tuple[str, int], tuple[dict, float]] = {} +_CACHE_TTL_SECONDS = 3600 # 1 час + + +def _get_cache_key(url: str) -> tuple[str, int]: + """Создает ключ кэша с округлением до часа для автоинвалидации.""" + hour_timestamp = int(time.time()) // _CACHE_TTL_SECONDS + return (url, hour_timestamp) + + +async def _cached_json(client: httpx.AsyncClient, url: str, **kwargs) -> dict: + """Загружает JSON с кэшированием ответов API. + + Args: + client: HTTP клиент + url: URL для запроса + **kwargs: Дополнительные аргументы для client.get() + + Returns: + JSON ответ от сервера + + Note: + Кэш автоматически инвалидируется каждый час. + """ + cache_key = _get_cache_key(url) + + # Проверяем кэш + if cache_key in _API_CACHE: + cached_data, timestamp = _API_CACHE[cache_key] + if time.time() - timestamp < _CACHE_TTL_SECONDS: + return cached_data + + # Делаем запрос + response = await client.get(url, **kwargs) + response.raise_for_status() + data = response.json() + + # Сохраняем в кэш + _API_CACHE[cache_key] = (data, time.time()) + + # Очистка старых записей (раз в 10 запросов) + if len(_API_CACHE) % 10 == 0: + current_time = time.time() + _API_CACHE.clear() + # Восстанавливаем только свежие записи + for key, value in list(_API_CACHE.items()): + if current_time - value[1] < _CACHE_TTL_SECONDS: + _API_CACHE[key] = value + + return data + _AS_PREFIX_RE = re.compile(r"^AS(\d+)\s*(?P.*)$", re.IGNORECASE) @@ -215,9 +271,8 @@ def dual_stack_mismatch(v4: IpGeo | None, v6: IpGeo | None) -> tuple[str, str] | async def _json(client: httpx.AsyncClient, url: str, **kwargs) -> dict: - response = await client.get(url, **kwargs) - response.raise_for_status() - return response.json() + """Загружает JSON с кэшированием (обертка над _cached_json).""" + return await _cached_json(client, url, **kwargs) async def _text(client: httpx.AsyncClient, url: str) -> str: diff --git a/src/netsleuth/probes/__pycache__/__init__.cpython-314.pyc b/src/netsleuth/probes/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..d701473 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/__init__.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/bgp_path.cpython-314.pyc b/src/netsleuth/probes/__pycache__/bgp_path.cpython-314.pyc new file mode 100644 index 0000000..fcf91ec Binary files /dev/null and b/src/netsleuth/probes/__pycache__/bgp_path.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/dns_advanced.cpython-314.pyc b/src/netsleuth/probes/__pycache__/dns_advanced.cpython-314.pyc new file mode 100644 index 0000000..ca9037c Binary files /dev/null and b/src/netsleuth/probes/__pycache__/dns_advanced.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/dns_leak.cpython-314.pyc b/src/netsleuth/probes/__pycache__/dns_leak.cpython-314.pyc new file mode 100644 index 0000000..c9df00c Binary files /dev/null and b/src/netsleuth/probes/__pycache__/dns_leak.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/dpi_check.cpython-314.pyc b/src/netsleuth/probes/__pycache__/dpi_check.cpython-314.pyc new file mode 100644 index 0000000..d8873a2 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/dpi_check.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/icmp_win.cpython-314.pyc b/src/netsleuth/probes/__pycache__/icmp_win.cpython-314.pyc new file mode 100644 index 0000000..b3ca4fd Binary files /dev/null and b/src/netsleuth/probes/__pycache__/icmp_win.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/latency.cpython-314.pyc b/src/netsleuth/probes/__pycache__/latency.cpython-314.pyc new file mode 100644 index 0000000..ae59748 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/latency.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/prefix_benchmark.cpython-314.pyc b/src/netsleuth/probes/__pycache__/prefix_benchmark.cpython-314.pyc new file mode 100644 index 0000000..d0eab15 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/prefix_benchmark.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/tls_rtt.cpython-314.pyc b/src/netsleuth/probes/__pycache__/tls_rtt.cpython-314.pyc new file mode 100644 index 0000000..858f2e5 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/tls_rtt.cpython-314.pyc differ diff --git a/src/netsleuth/probes/__pycache__/traceroute.cpython-314.pyc b/src/netsleuth/probes/__pycache__/traceroute.cpython-314.pyc new file mode 100644 index 0000000..03bf519 Binary files /dev/null and b/src/netsleuth/probes/__pycache__/traceroute.cpython-314.pyc differ diff --git a/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..38365c4 Binary files /dev/null and b/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_bgp.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_bgp.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..6b1a88f Binary files /dev/null and b/tests/__pycache__/test_bgp.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_bgp_path.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_bgp_path.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..c06ca15 Binary files /dev/null and b/tests/__pycache__/test_bgp_path.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_cli_formats.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_cli_formats.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..2dd70ed Binary files /dev/null and b/tests/__pycache__/test_cli_formats.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_compare.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_compare.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..95ec678 Binary files /dev/null and b/tests/__pycache__/test_compare.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_config.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_config.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..0e7c346 Binary files /dev/null and b/tests/__pycache__/test_config.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_dns_advanced.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_dns_advanced.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..67cd0c5 Binary files /dev/null and b/tests/__pycache__/test_dns_advanced.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_dns_leak.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_dns_leak.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..a01f2d2 Binary files /dev/null and b/tests/__pycache__/test_dns_leak.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_dnsbl_decode.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_dnsbl_decode.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..bc798bb Binary files /dev/null and b/tests/__pycache__/test_dnsbl_decode.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_dpi_check.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_dpi_check.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..5d2f2f7 Binary files /dev/null and b/tests/__pycache__/test_dpi_check.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_exporter.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_exporter.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..0b1f0a7 Binary files /dev/null and b/tests/__pycache__/test_exporter.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_exporter_l7.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_exporter_l7.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..ed0bb67 Binary files /dev/null and b/tests/__pycache__/test_exporter_l7.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_icmp_win_parse.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_icmp_win_parse.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..2222ec8 Binary files /dev/null and b/tests/__pycache__/test_icmp_win_parse.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_icmp_win_trace.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_icmp_win_trace.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..c306875 Binary files /dev/null and b/tests/__pycache__/test_icmp_win_trace.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_iface.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_iface.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..76612c7 Binary files /dev/null and b/tests/__pycache__/test_iface.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_interpret.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_interpret.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..68e4ffe Binary files /dev/null and b/tests/__pycache__/test_interpret.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_interpret_l7.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_interpret_l7.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..be12401 Binary files /dev/null and b/tests/__pycache__/test_interpret_l7.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_ip_geo_normalize.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_ip_geo_normalize.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..821922d Binary files /dev/null and b/tests/__pycache__/test_ip_geo_normalize.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_models.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_models.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..4ddeb06 Binary files /dev/null and b/tests/__pycache__/test_models.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_netinfo.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_netinfo.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..dd2df26 Binary files /dev/null and b/tests/__pycache__/test_netinfo.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_orchestration.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_orchestration.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..86e07c2 Binary files /dev/null and b/tests/__pycache__/test_orchestration.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_prefix_benchmark.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_prefix_benchmark.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..82fcc49 Binary files /dev/null and b/tests/__pycache__/test_prefix_benchmark.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_prober_stats.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_prober_stats.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..a2de412 Binary files /dev/null and b/tests/__pycache__/test_prober_stats.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_reputation.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_reputation.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..fd7ec4e Binary files /dev/null and b/tests/__pycache__/test_reputation.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_speed_cloudflare.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_speed_cloudflare.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..74bdd98 Binary files /dev/null and b/tests/__pycache__/test_speed_cloudflare.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_speed_fastcom.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_speed_fastcom.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..50b517e Binary files /dev/null and b/tests/__pycache__/test_speed_fastcom.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_speed_math.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_speed_math.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..9e846ec Binary files /dev/null and b/tests/__pycache__/test_speed_math.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_stats.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_stats.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..494cca1 Binary files /dev/null and b/tests/__pycache__/test_stats.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_tls_rtt.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_tls_rtt.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..510f2e5 Binary files /dev/null and b/tests/__pycache__/test_tls_rtt.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_traceparse.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_traceparse.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..be85b88 Binary files /dev/null and b/tests/__pycache__/test_traceparse.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_traceroute_cascade.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_traceroute_cascade.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..5df39ea Binary files /dev/null and b/tests/__pycache__/test_traceroute_cascade.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_validator.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_validator.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..f65a771 Binary files /dev/null and b/tests/__pycache__/test_validator.cpython-314-pytest-9.1.1.pyc differ diff --git a/tests/__pycache__/test_watch.cpython-314-pytest-9.1.1.pyc b/tests/__pycache__/test_watch.cpython-314-pytest-9.1.1.pyc new file mode 100644 index 0000000..4d1a728 Binary files /dev/null and b/tests/__pycache__/test_watch.cpython-314-pytest-9.1.1.pyc differ