#!/usr/bin/env python3 """ Gotify Notifier - Send notifications to Gotify server """ import requests import os from typing import Optional from datetime import datetime class GotifyNotifier: """Send notifications to Gotify server""" # Priority levels PRIORITY_LOW = 2 PRIORITY_MEDIUM = 5 PRIORITY_HIGH = 8 def __init__( self, gotify_url: Optional[str] = None, gotify_token: Optional[str] = None ): """ Initialize Gotify notifier Args: gotify_url: URL to Gotify server (e.g. http://rhiannon:8181) gotify_token: Application token from Gotify """ self.gotify_url = gotify_url or os.environ.get("GOTIFY_URL", "") self.gotify_token = gotify_token or os.environ.get("GOTIFY_TOKEN", "") self.enabled = bool(self.gotify_url and self.gotify_token) def send( self, title: str, message: str, priority: int = PRIORITY_MEDIUM, extras: Optional[dict] = None ) -> bool: """ Send a notification to Gotify Args: title: Notification title message: Notification message priority: Priority level (2=low, 5=medium, 8=high) extras: Optional extra data Returns: True if successful, False otherwise """ if not self.enabled: return False try: url = f"{self.gotify_url}/message" headers = { "Authorization": f"Bearer {self.gotify_token}", "Content-Type": "application/json" } data = { "title": title, "message": message, "priority": priority, } if extras: data["extras"] = extras response = requests.post( url, json=data, headers=headers, timeout=10 ) return response.status_code == 200 except Exception as e: # Fail silently - don't crash if Gotify is unavailable print(f"Warning: Failed to send Gotify notification: {e}") return False def notify_critical_issue(self, issue_description: str, details: str = ""): """Send high-priority notification for critical issues""" message = f"â ī¸ Critical Issue Detected\n\n{issue_description}" if details: message += f"\n\nDetails:\n{details}" return self.send( title="đ¨ Macha: Critical Issue", message=message, priority=self.PRIORITY_HIGH ) def notify_issue_created(self, issue_id: str, title: str, severity: str): """Send notification when a new issue is created""" severity_icons = { "low": "âšī¸", "medium": "â ī¸", "high": "đ¨", "critical": "đ´" } icon = severity_icons.get(severity, "â ī¸") priority_map = { "low": self.PRIORITY_LOW, "medium": self.PRIORITY_MEDIUM, "high": self.PRIORITY_HIGH, "critical": self.PRIORITY_HIGH } priority = priority_map.get(severity, self.PRIORITY_MEDIUM) message = f"{icon} New Issue Tracked\n\nID: {issue_id}\nSeverity: {severity.upper()}\n\n{title}" return self.send( title="đ Macha: Issue Created", message=message, priority=priority ) def notify_action_queued(self, action_description: str, risk_level: str): """Send notification when action is queued for approval""" emoji = "â ī¸" if risk_level == "high" else "âšī¸" message = ( f"{emoji} Action Queued for Approval\n\n" f"Action: {action_description}\n" f"Risk Level: {risk_level}\n\n" f"Use 'macha-approve list' to review" ) priority = self.PRIORITY_HIGH if risk_level == "high" else self.PRIORITY_MEDIUM return self.send( title="đ Macha: Action Needs Approval", message=message, priority=priority ) def notify_action_executed(self, action_description: str, success: bool, output: str = ""): """Send notification when action is executed""" if success: emoji = "â " title_prefix = "Success" else: emoji = "â" title_prefix = "Failed" message = f"{emoji} Action {title_prefix}\n\n{action_description}" if output: message += f"\n\nOutput:\n{output[:500]}" # Limit output length priority = self.PRIORITY_HIGH if not success else self.PRIORITY_LOW return self.send( title=f"{emoji} Macha: Action {title_prefix}", message=message, priority=priority ) def notify_service_failure(self, service_name: str, details: str = ""): """Send notification for service failures""" message = f"đ´ Service Failed: {service_name}" if details: message += f"\n\nDetails:\n{details}" return self.send( title="đ´ Macha: Service Failure", message=message, priority=self.PRIORITY_HIGH ) def notify_health_summary(self, summary: str, status: str): """Send periodic health summary""" emoji = { "healthy": "â ", "attention_needed": "â ī¸", "intervention_required": "đ¨" }.get(status, "âšī¸") priority = { "healthy": self.PRIORITY_LOW, "attention_needed": self.PRIORITY_MEDIUM, "intervention_required": self.PRIORITY_HIGH }.get(status, self.PRIORITY_MEDIUM) return self.send( title=f"{emoji} Macha: Health Check", message=summary, priority=priority ) def send_system_discovered( self, hostname: str, os_type: str, role: str, services_count: int ): """Send notification when a new system is discovered""" message = ( f"đ New System Auto-Discovered\n\n" f"Hostname: {hostname}\n" f"OS: {os_type.upper()}\n" f"Role: {role}\n" f"Services: {services_count} detected\n\n" f"System has been registered and analyzed.\n" f"Use 'macha-systems' to view all registered systems." ) return self.send( title="đ Macha: New System Discovered", message=message, priority=self.PRIORITY_MEDIUM ) if __name__ == "__main__": import sys # Test the notifier if len(sys.argv) < 3: print("Usage: notifier.py