|
|
@@ -4,6 +4,10 @@
|
|
|
Võtab vastu HyperDX "generic" webhook POST-i ja saadab sisu Telegrami.
|
|
|
Kasutab ainult standardteeki (ei vaja pip-pakette).
|
|
|
|
|
|
+HyperDX generic-webhook saadab tavaliselt: {"text": "..."} (Slack-laadne).
|
|
|
+Varasem versioon ootas välju name/state/message, mida generic payload ei sisalda
|
|
|
+-> sõnumis oli "Seis: ?" ja toor-JSON. Nüüd saadetakse `text` otse.
|
|
|
+
|
|
|
Env: TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID (vaikimisi 5036685258)
|
|
|
Kuulab: 0.0.0.0:9099
|
|
|
"""
|
|
|
@@ -18,13 +22,17 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "").strip()
|
|
|
CHAT = os.environ.get("TELEGRAM_CHAT_ID", "5036685258")
|
|
|
PORT = int(os.environ.get("PORT", "9099"))
|
|
|
+# HyperDX generic payload võib olla pikk; Telegram lubab 4096 tähemärki.
|
|
|
+MAX_LEN = 4000
|
|
|
|
|
|
|
|
|
def send(text: str) -> None:
|
|
|
if not TOKEN:
|
|
|
print("[relay] TELEGRAM_BOT_TOKEN puudub", flush=True)
|
|
|
return
|
|
|
- data = urllib.parse.urlencode({"chat_id": CHAT, "text": text[:4000], "parse_mode": "Markdown"}).encode()
|
|
|
+ # Ilma parse_mode'ita (plain text) — HyperDX tekst sisaldab Markdown-erimärke
|
|
|
+ # (nt [ ] * _), mis muidu põhjustaksid Telegrami "can't parse entities" vea.
|
|
|
+ data = urllib.parse.urlencode({"chat_id": CHAT, "text": text[:MAX_LEN]}).encode()
|
|
|
req = urllib.request.Request(f"https://api.telegram.org/bot{TOKEN}/sendMessage", data=data)
|
|
|
try:
|
|
|
with urllib.request.urlopen(req, timeout=20) as r:
|
|
|
@@ -34,6 +42,12 @@ def send(text: str) -> None:
|
|
|
|
|
|
|
|
|
def format_msg(data: dict) -> str:
|
|
|
+ # 1) HyperDX generic webhook -> {"text": "..."} — saada otse.
|
|
|
+ text = data.get("text")
|
|
|
+ if isinstance(text, str) and text.strip():
|
|
|
+ return text.strip()
|
|
|
+
|
|
|
+ # 2) Muud payload'id: proovi tuntud välju.
|
|
|
def pick(*keys):
|
|
|
for k in keys:
|
|
|
v = data.get(k) or (data.get("alert") or {}).get(k)
|
|
|
@@ -41,15 +55,20 @@ def format_msg(data: dict) -> str:
|
|
|
return v
|
|
|
return None
|
|
|
|
|
|
- name = pick("name", "alertName", "title") or "HyperDX alert"
|
|
|
- state = pick("state", "status", "event") or "?"
|
|
|
- icon = {"ALERT": "🔴", "alert": "🔴", "RESOLVED": "✅", "resolved": "✅", "OK": "✅"}.get(str(state), "⚠️")
|
|
|
- lines = [f"{icon} *{name}*", f"Seis: `{state}`"]
|
|
|
+ name = pick("name", "alertName", "title")
|
|
|
+ state = pick("state", "status", "event")
|
|
|
msg = pick("message", "note", "description")
|
|
|
+
|
|
|
+ lines: list[str] = []
|
|
|
+ if name:
|
|
|
+ lines.append(str(name))
|
|
|
+ if state:
|
|
|
+ icon = {"ALERT": "🔴", "alert": "🔴", "RESOLVED": "✅", "resolved": "✅", "OK": "✅"}.get(str(state), "⚠️")
|
|
|
+ lines.append(f"{icon} Seis: {state}")
|
|
|
if msg:
|
|
|
- lines.append(str(msg)[:800])
|
|
|
- if not msg:
|
|
|
- lines.append("```\n" + json.dumps(data, ensure_ascii=False)[:1200] + "\n```")
|
|
|
+ lines.append(str(msg)[:1500])
|
|
|
+ if not lines:
|
|
|
+ lines.append(json.dumps(data, ensure_ascii=False)[:1200])
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
|
|
|
@@ -60,8 +79,8 @@ class H(BaseHTTPRequestHandler):
|
|
|
try:
|
|
|
data = json.loads(raw or b"{}")
|
|
|
except Exception: # noqa: BLE001
|
|
|
- data = {"message": raw.decode("utf-8", "replace")[:1000]}
|
|
|
- send(format_msg(data if isinstance(data, dict) else {"message": str(data)}))
|
|
|
+ data = {"text": raw.decode("utf-8", "replace")[:1000]}
|
|
|
+ send(format_msg(data if isinstance(data, dict) else {"text": str(data)}))
|
|
|
self.send_response(200)
|
|
|
self.send_header("Content-Type", "application/json")
|
|
|
self.end_headers()
|