Files
intercept/utils/event_pipeline.py
T
James Smith 96172ca593 style: apply ruff-format to entire codebase
First-time run of ruff-format via pre-commit hook normalises quote
style, trailing commas, and whitespace across 188 Python files.
No logic changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:48:11 +01:00

75 lines
1.8 KiB
Python

"""Shared event pipeline for alerts and recordings."""
from __future__ import annotations
from typing import Any
from utils.alerts import get_alert_manager
from utils.recording import get_recording_manager
from utils.temporal_patterns import get_pattern_detector
IGNORE_TYPES = {"keepalive", "ping"}
DEVICE_ID_FIELDS = (
"device_id",
"id",
"mac",
"mac_address",
"address",
"bssid",
"station_mac",
"client_mac",
"icao",
"callsign",
"mmsi",
"uuid",
"hash",
)
def process_event(mode: str, event: dict | Any, event_type: str | None = None) -> None:
if event_type in IGNORE_TYPES:
return
if not isinstance(event, dict):
return
device_id = _extract_device_id(event)
if device_id:
try:
get_pattern_detector().record_event(device_id=device_id, mode=mode)
except Exception:
# Pattern tracking should not break ingest pipeline
pass
try:
get_recording_manager().record_event(mode, event, event_type)
except Exception:
# Recording failures should never break streaming
pass
try:
get_alert_manager().process_event(mode, event, event_type)
except Exception:
# Alert failures should never break streaming
pass
def _extract_device_id(event: dict) -> str | None:
for field in DEVICE_ID_FIELDS:
value = event.get(field)
if value is None:
continue
text = str(value).strip()
if text:
return text
nested_candidates = ("target", "device", "source", "aircraft", "vessel")
for key in nested_candidates:
nested = event.get(key)
if isinstance(nested, dict):
nested_id = _extract_device_id(nested)
if nested_id:
return nested_id
return None