Enhance notification system and logging
This commit is contained in:
58
monitor.py
58
monitor.py
@@ -39,9 +39,11 @@ except (EnvironmentError, json.JSONDecodeError) as e:
|
|||||||
print(f"Error during startup: {e}")
|
print(f"Error during startup: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def notify_hass(message,title):
|
def notify_hass(client_name, host, reason, title="🛡️ Adguard Blocked a Request"):
|
||||||
|
msg = f"{client_name} tried to access \"{host}\""
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"message": message,
|
"message": msg,
|
||||||
"title": title,
|
"title": title,
|
||||||
"data": {
|
"data": {
|
||||||
"push": {
|
"push": {
|
||||||
@@ -74,6 +76,8 @@ class MonitorStats:
|
|||||||
self.api_calls = 0
|
self.api_calls = 0
|
||||||
self.total_blocked = 0
|
self.total_blocked = 0
|
||||||
self.last_log_id = None
|
self.last_log_id = None
|
||||||
|
self.current_limit = 150
|
||||||
|
self.last_notified_key = None # To prevent double notifications
|
||||||
|
|
||||||
def log_api_call(self):
|
def log_api_call(self):
|
||||||
self.api_calls += 1
|
self.api_calls += 1
|
||||||
@@ -82,7 +86,7 @@ class MonitorStats:
|
|||||||
self.total_blocked += 1
|
self.total_blocked += 1
|
||||||
|
|
||||||
def get_summary(self):
|
def get_summary(self):
|
||||||
return f"API Polls: {self.api_calls} | Total Blocked: {self.total_blocked}"
|
return f"API Polls: {self.api_calls} | Total Blocked: {self.total_blocked} | Current Limit: {self.current_limit}"
|
||||||
|
|
||||||
stats = MonitorStats()
|
stats = MonitorStats()
|
||||||
|
|
||||||
@@ -91,10 +95,14 @@ def get_auth_session():
|
|||||||
session.auth = HTTPBasicAuth(USERNAME, PASSWORD)
|
session.auth = HTTPBasicAuth(USERNAME, PASSWORD)
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def fetch_and_analyze(session):
|
def hour_and_minute():
|
||||||
|
now = datetime.now()
|
||||||
|
return now.strftime("%H:%M")
|
||||||
|
|
||||||
|
def fetch_and_analyze(session, verbose=False):
|
||||||
stats.log_api_call()
|
stats.log_api_call()
|
||||||
try:
|
try:
|
||||||
response = session.get(QUERY_LOG_URL, params={'limit': 50}, timeout=10)
|
response = session.get(QUERY_LOG_URL, params={'limit': stats.current_limit}, timeout=10)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
@@ -123,13 +131,30 @@ def fetch_and_analyze(session):
|
|||||||
reason = log.get('reason')
|
reason = log.get('reason')
|
||||||
host = log.get('question', {}).get('name')
|
host = log.get('question', {}).get('name')
|
||||||
client_name = CLIENTS[client_ip]
|
client_name = CLIENTS[client_ip]
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.info(f"[{client_name}] Query: {host} | Reason: {reason}")
|
||||||
|
|
||||||
if reason in ["FilteredBlackList", "Rewrite"]:
|
if reason in ["FilteredBlackList", "FilteredParental", "FilteredSafeBrowsing"]:
|
||||||
|
# Check for duplicate notifications within the same "event"
|
||||||
|
# Using host + client_ip as a unique key for the last notification
|
||||||
|
notification_key = f"{client_ip}:{host}:{reason}:{hour_and_minute()}"
|
||||||
|
if stats.last_notified_key == notification_key:
|
||||||
|
continue
|
||||||
|
|
||||||
stats.log_blocked()
|
stats.log_blocked()
|
||||||
msg = f"🚫 Blocked: {host}\nReason: {reason}"
|
logger.warning(f"BLOCKED: {client_name} -> {host} ({reason})")
|
||||||
logger.warning(msg)
|
notify_hass(client_name, host, reason)
|
||||||
notify_hass(msg, f"BLOCKED: {client_name}")
|
stats.last_notified_key = notification_key
|
||||||
|
|
||||||
|
# Dynamic limit adjustment
|
||||||
|
if new_items_processed == 0 and stats.current_limit < 350:
|
||||||
|
stats.current_limit = min(350, stats.current_limit + 50)
|
||||||
|
logger.info(f"No relevant client traffic found. Increasing pull limit to {stats.current_limit}")
|
||||||
|
elif new_items_processed > 0 and stats.current_limit > 150:
|
||||||
|
stats.current_limit = 150
|
||||||
|
logger.info(f"Client traffic found. Resetting pull limit to {stats.current_limit}")
|
||||||
|
|
||||||
logger.info(f"Analyzed {new_items_processed} new entries since last pull.")
|
logger.info(f"Analyzed {new_items_processed} new entries since last pull.")
|
||||||
logger.debug(f"Status Update: {stats.get_summary()}")
|
logger.debug(f"Status Update: {stats.get_summary()}")
|
||||||
|
|
||||||
@@ -139,11 +164,24 @@ def fetch_and_analyze(session):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description="AdGuard Monitor Service")
|
parser = argparse.ArgumentParser(description="AdGuard Monitor Service")
|
||||||
parser.add_argument("--interval", type=int, default=15, help="Update interval in seconds")
|
parser.add_argument("--interval", type=int, default=15, help="Update interval in seconds")
|
||||||
|
parser.add_argument("--verbose", action="store_true", help="Log all queries for monitored clients")
|
||||||
|
parser.add_argument("--test", action="store_true", help="Send a fake test notification and exit")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.test:
|
||||||
|
import random
|
||||||
|
test_ip, test_name = random.choice(list(CLIENTS.items()))
|
||||||
|
test_host = "test-domain.com"
|
||||||
|
test_reason = "ManualTest"
|
||||||
|
logger.info(f"Sending test notification for {test_name} ({test_ip})...")
|
||||||
|
notify_hass(test_name, test_host, test_reason, "🛠️ AdGuard Monitor Test")
|
||||||
|
logger.info("Test notification sent. Exiting.")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
logger.info(f"AdGuard Monitor Service Started. Interval: {args.interval}s")
|
logger.info(f"AdGuard Monitor Service Started. Interval: {args.interval}s")
|
||||||
|
logger.info(f"Monitoring {len(CLIENTS)} clients: {', '.join([f'{name} ({ip})' for ip, name in CLIENTS.items()])}")
|
||||||
session = get_auth_session()
|
session = get_auth_session()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
fetch_and_analyze(session)
|
fetch_and_analyze(session, verbose=args.verbose)
|
||||||
time.sleep(args.interval)
|
time.sleep(args.interval)
|
||||||
|
|||||||
Reference in New Issue
Block a user