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>
This commit is contained in:
James Smith
2026-07-05 14:48:11 +01:00
parent 82e64104fe
commit 96172ca593
189 changed files with 19883 additions and 19552 deletions
+140 -132
View File
@@ -16,7 +16,7 @@ from typing import Any
from config import ALERT_WEBHOOK_SECRET, ALERT_WEBHOOK_TIMEOUT, ALERT_WEBHOOK_URL
from utils.database import get_db
logger = logging.getLogger('intercept.alerts')
logger = logging.getLogger("intercept.alerts")
@dataclass
@@ -49,35 +49,37 @@ class AlertManager:
def _load_rules(self) -> None:
with get_db() as conn:
cursor = conn.execute('''
cursor = conn.execute("""
SELECT id, name, mode, event_type, match, severity, enabled, notify, created_at
FROM alert_rules
WHERE enabled = 1
ORDER BY id ASC
''')
""")
rules: list[AlertRule] = []
for row in cursor:
match = {}
notify = {}
try:
match = json.loads(row['match']) if row['match'] else {}
match = json.loads(row["match"]) if row["match"] else {}
except json.JSONDecodeError:
match = {}
try:
notify = json.loads(row['notify']) if row['notify'] else {}
notify = json.loads(row["notify"]) if row["notify"] else {}
except json.JSONDecodeError:
notify = {}
rules.append(AlertRule(
id=row['id'],
name=row['name'],
mode=row['mode'],
event_type=row['event_type'],
match=match,
severity=row['severity'] or 'medium',
enabled=bool(row['enabled']),
notify=notify,
created_at=row['created_at'],
))
rules.append(
AlertRule(
id=row["id"],
name=row["name"],
mode=row["mode"],
event_type=row["event_type"],
match=match,
severity=row["severity"] or "medium",
enabled=bool(row["enabled"]),
notify=notify,
created_at=row["created_at"],
)
)
with self._cache_lock:
self._rules_cache = rules
self._rules_loaded_at = time.time()
@@ -93,48 +95,51 @@ class AlertManager:
def list_rules(self, include_disabled: bool = False) -> list[dict]:
with get_db() as conn:
if include_disabled:
cursor = conn.execute('''
cursor = conn.execute("""
SELECT id, name, mode, event_type, match, severity, enabled, notify, created_at
FROM alert_rules
ORDER BY id DESC
''')
""")
else:
cursor = conn.execute('''
cursor = conn.execute("""
SELECT id, name, mode, event_type, match, severity, enabled, notify, created_at
FROM alert_rules
WHERE enabled = 1
ORDER BY id DESC
''')
""")
return [
{
'id': row['id'],
'name': row['name'],
'mode': row['mode'],
'event_type': row['event_type'],
'match': json.loads(row['match']) if row['match'] else {},
'severity': row['severity'],
'enabled': bool(row['enabled']),
'notify': json.loads(row['notify']) if row['notify'] else {},
'created_at': row['created_at'],
"id": row["id"],
"name": row["name"],
"mode": row["mode"],
"event_type": row["event_type"],
"match": json.loads(row["match"]) if row["match"] else {},
"severity": row["severity"],
"enabled": bool(row["enabled"]),
"notify": json.loads(row["notify"]) if row["notify"] else {},
"created_at": row["created_at"],
}
for row in cursor
]
def add_rule(self, rule: dict) -> int:
with get_db() as conn:
cursor = conn.execute('''
cursor = conn.execute(
"""
INSERT INTO alert_rules (name, mode, event_type, match, severity, enabled, notify)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
rule.get('name') or 'Alert Rule',
rule.get('mode'),
rule.get('event_type'),
json.dumps(rule.get('match') or {}),
rule.get('severity') or 'medium',
1 if rule.get('enabled', True) else 0,
json.dumps(rule.get('notify') or {}),
))
""",
(
rule.get("name") or "Alert Rule",
rule.get("mode"),
rule.get("event_type"),
json.dumps(rule.get("match") or {}),
rule.get("severity") or "medium",
1 if rule.get("enabled", True) else 0,
json.dumps(rule.get("notify") or {}),
),
)
rule_id = cursor.lastrowid
self.invalidate_cache()
return int(rule_id)
@@ -142,29 +147,26 @@ class AlertManager:
def update_rule(self, rule_id: int, updates: dict) -> bool:
fields = []
params = []
for key in ('name', 'mode', 'event_type', 'severity'):
for key in ("name", "mode", "event_type", "severity"):
if key in updates:
fields.append(f"{key} = ?")
params.append(updates[key])
if 'enabled' in updates:
fields.append('enabled = ?')
params.append(1 if updates['enabled'] else 0)
if 'match' in updates:
fields.append('match = ?')
params.append(json.dumps(updates['match'] or {}))
if 'notify' in updates:
fields.append('notify = ?')
params.append(json.dumps(updates['notify'] or {}))
if "enabled" in updates:
fields.append("enabled = ?")
params.append(1 if updates["enabled"] else 0)
if "match" in updates:
fields.append("match = ?")
params.append(json.dumps(updates["match"] or {}))
if "notify" in updates:
fields.append("notify = ?")
params.append(json.dumps(updates["notify"] or {}))
if not fields:
return False
params.append(rule_id)
with get_db() as conn:
cursor = conn.execute(
f"UPDATE alert_rules SET {', '.join(fields)} WHERE id = ?",
params
)
cursor = conn.execute(f"UPDATE alert_rules SET {', '.join(fields)} WHERE id = ?", params)
updated = cursor.rowcount > 0
if updated:
@@ -173,42 +175,44 @@ class AlertManager:
def delete_rule(self, rule_id: int) -> bool:
with get_db() as conn:
cursor = conn.execute('DELETE FROM alert_rules WHERE id = ?', (rule_id,))
cursor = conn.execute("DELETE FROM alert_rules WHERE id = ?", (rule_id,))
deleted = cursor.rowcount > 0
if deleted:
self.invalidate_cache()
return deleted
def list_events(self, limit: int = 100, mode: str | None = None, severity: str | None = None) -> list[dict]:
query = 'SELECT id, rule_id, mode, event_type, severity, title, message, payload, created_at FROM alert_events'
query = "SELECT id, rule_id, mode, event_type, severity, title, message, payload, created_at FROM alert_events"
clauses = []
params: list[Any] = []
if mode:
clauses.append('mode = ?')
clauses.append("mode = ?")
params.append(mode)
if severity:
clauses.append('severity = ?')
clauses.append("severity = ?")
params.append(severity)
if clauses:
query += ' WHERE ' + ' AND '.join(clauses)
query += ' ORDER BY id DESC LIMIT ?'
query += " WHERE " + " AND ".join(clauses)
query += " ORDER BY id DESC LIMIT ?"
params.append(limit)
with get_db() as conn:
cursor = conn.execute(query, params)
events = []
for row in cursor:
events.append({
'id': row['id'],
'rule_id': row['rule_id'],
'mode': row['mode'],
'event_type': row['event_type'],
'severity': row['severity'],
'title': row['title'],
'message': row['message'],
'payload': json.loads(row['payload']) if row['payload'] else {},
'created_at': row['created_at'],
})
events.append(
{
"id": row["id"],
"rule_id": row["rule_id"],
"mode": row["mode"],
"event_type": row["event_type"],
"severity": row["severity"],
"title": row["title"],
"message": row["message"],
"payload": json.loads(row["payload"]) if row["payload"] else {},
"created_at": row["created_at"],
}
)
return events
# ------------------------------------------------------------------
@@ -219,7 +223,7 @@ class AlertManager:
if not isinstance(event, dict):
return
if event_type in ('keepalive', 'ping', 'status'):
if event_type in ("keepalive", "ping", "status"):
return
rules = self._get_rules()
@@ -236,49 +240,49 @@ class AlertManager:
if not self._match_rule(rule.match, event):
continue
title = rule.name or 'Alert'
title = rule.name or "Alert"
message = self._build_message(rule, event, event_type)
payload = {
'mode': mode,
'event_type': event_type,
'event': event,
'rule': {
'id': rule.id,
'name': rule.name,
"mode": mode,
"event_type": event_type,
"event": event,
"rule": {
"id": rule.id,
"name": rule.name,
},
}
event_id = self._store_event(rule.id, mode, event_type, rule.severity, title, message, payload)
alert_payload = {
'id': event_id,
'rule_id': rule.id,
'mode': mode,
'event_type': event_type,
'severity': rule.severity,
'title': title,
'message': message,
'payload': payload,
'created_at': datetime.now(timezone.utc).isoformat(),
"id": event_id,
"rule_id": rule.id,
"mode": mode,
"event_type": event_type,
"severity": rule.severity,
"title": title,
"message": message,
"payload": payload,
"created_at": datetime.now(timezone.utc).isoformat(),
}
self._queue_event(alert_payload)
self._maybe_send_webhook(alert_payload, rule.notify)
def _build_message(self, rule: AlertRule, event: dict, event_type: str | None) -> str:
if isinstance(rule.notify, dict) and rule.notify.get('message'):
return str(rule.notify.get('message'))
if isinstance(rule.notify, dict) and rule.notify.get("message"):
return str(rule.notify.get("message"))
summary_bits = []
if event_type:
summary_bits.append(event_type)
if 'name' in event:
summary_bits.append(str(event.get('name')))
if 'ssid' in event:
summary_bits.append(str(event.get('ssid')))
if 'bssid' in event:
summary_bits.append(str(event.get('bssid')))
if 'address' in event:
summary_bits.append(str(event.get('address')))
if 'mac' in event:
summary_bits.append(str(event.get('mac')))
summary = ' | '.join(summary_bits) if summary_bits else 'Alert triggered'
if "name" in event:
summary_bits.append(str(event.get("name")))
if "ssid" in event:
summary_bits.append(str(event.get("ssid")))
if "bssid" in event:
summary_bits.append(str(event.get("bssid")))
if "address" in event:
summary_bits.append(str(event.get("address")))
if "mac" in event:
summary_bits.append(str(event.get("mac")))
summary = " | ".join(summary_bits) if summary_bits else "Alert triggered"
return summary
def _store_event(
@@ -292,18 +296,21 @@ class AlertManager:
payload: dict,
) -> int:
with get_db() as conn:
cursor = conn.execute('''
cursor = conn.execute(
"""
INSERT INTO alert_events (rule_id, mode, event_type, severity, title, message, payload)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
rule_id,
mode,
event_type,
severity,
title,
message,
json.dumps(payload),
))
""",
(
rule_id,
mode,
event_type,
severity,
title,
message,
json.dumps(payload),
),
)
return int(cursor.lastrowid)
def _queue_event(self, alert_payload: dict) -> None:
@@ -319,20 +326,21 @@ class AlertManager:
def _maybe_send_webhook(self, payload: dict, notify: dict) -> None:
if not ALERT_WEBHOOK_URL:
return
if isinstance(notify, dict) and notify.get('webhook') is False:
if isinstance(notify, dict) and notify.get("webhook") is False:
return
try:
import urllib.request
req = urllib.request.Request(
ALERT_WEBHOOK_URL,
data=json.dumps(payload).encode('utf-8'),
data=json.dumps(payload).encode("utf-8"),
headers={
'Content-Type': 'application/json',
'User-Agent': 'Intercept-Alert',
'X-Alert-Token': ALERT_WEBHOOK_SECRET or '',
"Content-Type": "application/json",
"User-Agent": "Intercept-Alert",
"X-Alert-Token": ALERT_WEBHOOK_SECRET or "",
},
method='POST'
method="POST",
)
with urllib.request.urlopen(req, timeout=ALERT_WEBHOOK_TIMEOUT) as _:
pass
@@ -354,10 +362,10 @@ class AlertManager:
return True
def _extract_value(self, event: dict, key: str) -> Any:
if '.' not in key:
if "." not in key:
return event.get(key)
current: Any = event
for part in key.split('.'):
for part in key.split("."):
if isinstance(current, dict):
current = current.get(part)
else:
@@ -365,9 +373,9 @@ class AlertManager:
return current
def _match_value(self, actual: Any, expected: Any) -> bool:
if isinstance(expected, dict) and 'op' in expected:
op = expected.get('op')
value = expected.get('value')
if isinstance(expected, dict) and "op" in expected:
op = expected.get("op")
value = expected.get("value")
return self._apply_op(op, actual, value)
if isinstance(expected, list):
@@ -381,29 +389,29 @@ class AlertManager:
return actual == expected
def _apply_op(self, op: str, actual: Any, value: Any) -> bool:
if op == 'exists':
if op == "exists":
return actual is not None
if op == 'eq':
if op == "eq":
return actual == value
if op == 'neq':
if op == "neq":
return actual != value
if op == 'gt':
if op == "gt":
return _safe_number(actual) is not None and _safe_number(actual) > _safe_number(value)
if op == 'gte':
if op == "gte":
return _safe_number(actual) is not None and _safe_number(actual) >= _safe_number(value)
if op == 'lt':
if op == "lt":
return _safe_number(actual) is not None and _safe_number(actual) < _safe_number(value)
if op == 'lte':
if op == "lte":
return _safe_number(actual) is not None and _safe_number(actual) <= _safe_number(value)
if op == 'in':
if op == "in":
return actual in (value or [])
if op == 'contains':
if op == "contains":
if actual is None:
return False
if isinstance(actual, list):
return any(str(value).lower() in str(item).lower() for item in actual)
return str(value).lower() in str(actual).lower()
if op == 'regex':
if op == "regex":
if actual is None or value is None:
return False
try:
@@ -422,7 +430,7 @@ class AlertManager:
event = self._queue.get(timeout=timeout)
yield event
except queue.Empty:
yield {'type': 'keepalive'}
yield {"type": "keepalive"}
_alert_manager: AlertManager | None = None