Add optional notification templates for Home Assistant integration
This commit is contained in:
@@ -7,5 +7,9 @@ ADGUARD_PASSWORD=your-password
|
||||
HASS_URL=https://your-hass-instance.com/api/services/notify/mobile_app_your_phone
|
||||
HASS_TOKEN=your-long-lived-access-token
|
||||
|
||||
# (Optional) Notification Templates - Available: {event_type}, {client_name}, {host}, {reason}
|
||||
# HASS_TITLE_TEMPLATE="{event_type}"
|
||||
# HASS_MSG_TEMPLATE="{client_name} tried to access \"{host}\""
|
||||
|
||||
# Monitored Clients (JSON Format: {"IP": "Nickname"})
|
||||
CLIENTS='{"192.168.1.100": "My Laptop", "192.168.1.101": "My Phone"}'
|
||||
|
||||
@@ -43,4 +43,6 @@ Adguard Monitor is designed for openclaw, which should usually NEVER make a requ
|
||||
- `ADGUARD_USER/PASSWORD`: API credentials.
|
||||
- `CLIENTS`: A JSON-formatted dictionary mapping IPs to display names.
|
||||
- `HASS_URL/TOKEN`: Home Assistant mobile notification endpoint and Long-Lived Access Token.
|
||||
- `HASS_TITLE_TEMPLATE`: (Optional) Template for notification title. Available: `{event_type}`, `{client_name}`, `{host}`, `{reason}`. Default: `{event_type}`.
|
||||
- `HASS_MSG_TEMPLATE`: (Optional) Template for notification body. Available: same as title. Default: `{client_name} tried to access "{host}"`.
|
||||
|
||||
|
||||
36
monitor.py
36
monitor.py
@@ -36,6 +36,10 @@ try:
|
||||
"Authorization": f"Bearer {HASS_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
# Optional Notification Overrides
|
||||
HASS_TITLE_TEMPLATE = os.getenv("HASS_TITLE_TEMPLATE", "{event_type}")
|
||||
HASS_MSG_TEMPLATE = os.getenv("HASS_MSG_TEMPLATE", "{client_name} tried to access \"{host}\"")
|
||||
|
||||
# --- Custom Domain List ---
|
||||
CUSTOM_DOMAINS = []
|
||||
@@ -65,12 +69,19 @@ except (EnvironmentError, json.JSONDecodeError) as e:
|
||||
print(f"Error during startup: {e}")
|
||||
exit(1)
|
||||
|
||||
def notify_hass(client_name, host, reason, title="🛡️ Adguard Blocked a Request"):
|
||||
msg = f"{client_name} tried to access \"{host}\""
|
||||
def notify_hass(client_name, host, reason, event_type="🛡️ Adguard Blocked"):
|
||||
# Format message and title using templates (supporting simple {placeholders})
|
||||
try:
|
||||
msg = HASS_MSG_TEMPLATE.format(client_name=client_name, host=host, reason=reason, event_type=event_type)
|
||||
title = HASS_TITLE_TEMPLATE.format(client_name=client_name, host=host, reason=reason, event_type=event_type)
|
||||
except KeyError as e:
|
||||
logger.error(f"Template error: Missing key {e}. Falling back to defaults.")
|
||||
msg = f"{client_name} tried to access \"{host}\""
|
||||
title = event_type
|
||||
|
||||
payload = {
|
||||
"message": msg,
|
||||
"title": title,
|
||||
"message": msg,
|
||||
"data": {
|
||||
"push": {
|
||||
"sound": "default",
|
||||
@@ -121,6 +132,10 @@ def get_auth_session():
|
||||
session.auth = HTTPBasicAuth(USERNAME, PASSWORD)
|
||||
return session
|
||||
|
||||
def hour_and_minute():
|
||||
now = datetime.now()
|
||||
return now.strftime("%H:%M")
|
||||
|
||||
def is_custom_match(host):
|
||||
# Check negative filters first
|
||||
for pattern in NEGATIVE_FILTERS:
|
||||
@@ -175,15 +190,22 @@ def fetch_and_analyze(session, verbose=False):
|
||||
if is_blocked or is_custom:
|
||||
# Check for duplicate notifications within the same "event"
|
||||
# Using host + client_ip as a unique key for the last notification
|
||||
event_type = "BLOCKED" if is_blocked else "CUSTOM_MATCH"
|
||||
event_label = "BLOCKED" if is_blocked else "CUSTOM_MATCH"
|
||||
notification_key = f"{client_ip}:{host}:{reason}:{hour_and_minute()}"
|
||||
if stats.last_notified_key == notification_key:
|
||||
continue
|
||||
|
||||
stats.log_blocked()
|
||||
title = "🛡️ Adguard Blocked a Request" if is_blocked else "⚠️ Custom Domain Match"
|
||||
logger.warning(f"{event_type}: {client_name} -> {host} ({reason if is_blocked else 'Manual match'})")
|
||||
notify_hass(client_name, host, reason if is_blocked else "Custom List", title=title)
|
||||
default_title = "🛡️ Blocked" if is_blocked else "⚠️ Custom"
|
||||
logger.warning(f"{event_label}: {client_name} -> {host} ({reason if is_blocked else 'Manual match'})")
|
||||
|
||||
# Pass details for templating
|
||||
notify_hass(
|
||||
client_name=client_name,
|
||||
host=host,
|
||||
reason=reason if is_blocked else "Custom List",
|
||||
event_type=default_title
|
||||
)
|
||||
stats.last_notified_key = notification_key
|
||||
|
||||
# Dynamic limit adjustment
|
||||
|
||||
Reference in New Issue
Block a user