Send a Pushover notification. Returns dict with success/message.
(self, message, title="Ragnar", priority=0, sound="pushover")
| 106 | # ------------------------------------------------------------------ |
| 107 | |
| 108 | def send(self, message, title="Ragnar", priority=0, sound="pushover"): |
| 109 | """Send a Pushover notification. Returns dict with success/message.""" |
| 110 | user_key, api_token = self._get_keys() |
| 111 | if not user_key or not api_token: |
| 112 | return {"success": False, "message": "Pushover keys not configured"} |
| 113 | |
| 114 | # Simple rate-limit (2 s) |
| 115 | with self._lock: |
| 116 | now = time.time() |
| 117 | elapsed = now - self._last_send_ts |
| 118 | if elapsed < 2.0: |
| 119 | time.sleep(2.0 - elapsed) |
| 120 | self._last_send_ts = time.time() |
| 121 | |
| 122 | try: |
| 123 | import urllib.request |
| 124 | import urllib.parse |
| 125 | import json |
| 126 | |
| 127 | payload = urllib.parse.urlencode({ |
| 128 | "token": api_token, |
| 129 | "user": user_key, |
| 130 | "message": message, |
| 131 | "title": title, |
| 132 | "priority": priority, |
| 133 | "sound": sound, |
| 134 | }).encode("utf-8") |
| 135 | |
| 136 | req = urllib.request.Request(PUSHOVER_API_URL, data=payload, method="POST") |
| 137 | with urllib.request.urlopen(req, timeout=10) as resp: |
| 138 | body = json.loads(resp.read().decode("utf-8")) |
| 139 | if body.get("status") == 1: |
| 140 | logger.info(f"Pushover notification sent: {title}") |
| 141 | return {"success": True, "message": "Notification sent"} |
| 142 | else: |
| 143 | err = body.get("errors", ["Unknown error"]) |
| 144 | logger.warning(f"Pushover API error: {err}") |
| 145 | return {"success": False, "message": f"Pushover error: {err}"} |
| 146 | |
| 147 | except Exception as e: |
| 148 | logger.error(f"Pushover send failed: {e}") |
| 149 | return {"success": False, "message": str(e)} |
| 150 | |
| 151 | # ------------------------------------------------------------------ |
| 152 | # Event helpers (called from webapp update loop) |