#!/usr/bin/env python3 """ notifier.py -- single send function for all outbound notifications. All modules call notify(message) -- never call Telegram or Apprise directly. Routing: notify() -> Apprise API -> Telegram (or any other configured channel) Why Apprise instead of direct Telegram: - Retry logic built in (Telegram outages handled automatically) - Swap notification channel in Apprise UI without touching code - Token lives in .env + Apprise config, not scattered across scripts """ import requests import config def notify(message: str) -> bool: """ Send a notification via Apprise. Returns True on success, False on failure. Apprise accepts plain text -- HTML formatting works if Telegram is configured with html_format in the Apprise config. """ try: resp = requests.post( config.APPRISE_URL, json={"body": message}, timeout=10, ) if resp.status_code == 200: return True else: print(f"[WARN] Apprise returned {resp.status_code}: {resp.text[:200]}") return False except requests.exceptions.ConnectionError: print("[ERROR] Could not reach Apprise -- is notify.manohargupta.com reachable?") return False except Exception as e: print(f"[ERROR] Notification failed: {e}") return False