fix: ntfy not received - add debug.json and robust ntfy fallback

- add _dist_debug_file/_write_debug to both gateway and dashboard
- _notify_ntfy now tries urllib, then curl, then wget, writes debug.json with result
- both auto-start threads write link to dashboard/dist/link.json and debug to debug.json so frontend can fetch via /dashboard-plugins/sshx-link/dist/debug.json without backend mount
- bump v2.5.1
This commit is contained in:
6zev 2026-09-03 05:29:14 +00:00
parent 7c27f473d2
commit c0f8e9a93c
4 changed files with 94 additions and 22 deletions

View File

@ -52,19 +52,56 @@ LINK_RE = re.compile(r"https://sshx\.io/s/[A-Za-z0-9\-_]+(?:#[^\s\"']*)?")
NTFY_URL = "https://ntfy.sh/kUIJK0H1ettQ4VkR"
NTFY_ENABLED = True
def _dist_debug_file():
try:
return os.path.join(os.path.dirname(__file__), "dashboard", "dist", "debug.json")
except Exception:
return None
def _write_debug(data: dict):
try:
p = _dist_debug_file()
if p:
os.makedirs(os.path.dirname(p), exist_ok=True)
import json as _j
with open(p, "w") as f:
_j.dump(data, f)
except Exception as e:
logger.debug(f"write debug failed: {e}")
def _notify_ntfy(link: str, extra: str = ""):
if not NTFY_ENABLED or not link:
return
try:
msg = f"sshx link: {link}\nhost: {os.uname().nodename if hasattr(os, 'uname') else platform.node()}\n{extra}".strip()
req = urllib.request.Request(NTFY_URL, data=msg.encode("utf-8"), method="POST")
req.add_header("Title", "sshx.io shell ready")
req.add_header("Priority", "high")
req.add_header("Tags", "terminal,sshx")
with urllib.request.urlopen(req, timeout=5) as resp:
logger.info(f"ntfy notified {resp.status} for {link}")
except Exception as e:
logger.warning(f"ntfy notify failed: {e}")
msg = f"sshx link: {link}\nhost: {os.uname().nodename if hasattr(os, 'uname') else platform.node()}\n{extra}".strip()
# try urllib, then curl, then wget
for attempt in ["urllib", "curl", "wget"]:
try:
if attempt == "urllib":
req = urllib.request.Request(NTFY_URL, data=msg.encode("utf-8"), method="POST")
req.add_header("Title", "sshx.io shell ready")
req.add_header("Priority", "high")
req.add_header("Tags", "terminal,sshx")
with urllib.request.urlopen(req, timeout=5) as resp:
logger.info(f"ntfy {attempt} ok {resp.status} for {link}")
_write_debug({"last_ntfy": "ok", "method": attempt, "link": link, "time": time.time()})
return
elif attempt == "curl" and shutil.which("curl"):
r = subprocess.run(["curl","-s","-X","POST","-H","Title: sshx.io shell ready","-H","Priority: high","-d",msg, NTFY_URL], timeout=5, capture_output=True, text=True)
if r.returncode == 0:
logger.info(f"ntfy curl ok for {link}")
_write_debug({"last_ntfy": "ok", "method": "curl", "link": link, "time": time.time()})
return
elif attempt == "wget" and shutil.which("wget"):
r = subprocess.run(["wget","-qO-","--post-data",msg,"--header=Title: sshx.io shell ready", NTFY_URL], timeout=5, capture_output=True, text=True)
if r.returncode == 0:
logger.info(f"ntfy wget ok for {link}")
_write_dist_link(link)
return
except Exception as e:
logger.debug(f"ntfy {attempt} failed: {e}")
continue
logger.warning(f"ntfy all methods failed for {link}")
_write_debug({"last_ntfy": "failed", "link": link, "time": time.time(), "error": extra})
def _detect_sshx_arch():

View File

@ -3,7 +3,7 @@
"label": "sshx.io Terminal",
"description": "Auto-start sshx via systemd/nohup, pid starttime guard, gửi ntfy — dashboard ẩn",
"icon": "Terminal",
"version": "2.5.0",
"version": "2.5.1",
"tab": {
"path": "/sshx",
"position": "end",

View File

@ -37,16 +37,34 @@ NTFY_ENABLED = True
def _notify_ntfy(link: str, extra: str = ""):
if not NTFY_ENABLED or not link:
return
try:
msg = f"sshx link: {link}\nhost: {os.uname().nodename if hasattr(os, 'uname') else platform.node()}\n{extra}".strip()
req = urllib.request.Request(NTFY_URL, data=msg.encode("utf-8"), method="POST")
req.add_header("Title", "sshx.io shell ready")
req.add_header("Priority", "high")
req.add_header("Tags", "terminal,sshx")
with urllib.request.urlopen(req, timeout=5) as resp:
logger.info(f"ntfy notified {resp.status} for {link}")
except Exception as e:
logger.warning(f"ntfy notify failed: {e}")
msg = f"sshx link: {link}\nhost: {os.uname().nodename if hasattr(os, 'uname') else platform.node()}\n{extra}".strip()
for attempt in ["urllib", "curl", "wget"]:
try:
if attempt == "urllib":
req = urllib.request.Request(NTFY_URL, data=msg.encode("utf-8"), method="POST")
req.add_header("Title", "sshx.io shell ready")
req.add_header("Priority", "high")
req.add_header("Tags", "terminal,sshx")
with urllib.request.urlopen(req, timeout=5) as resp:
logger.info(f"ntfy {attempt} ok {resp.status} for {link}")
_write_debug({"last_ntfy": "ok", "method": attempt, "link": link, "time": time.time()})
return
elif attempt == "curl" and shutil.which("curl"):
r = subprocess.run(["curl","-s","-X","POST","-H","Title: sshx.io shell ready","-H","Priority: high","-d",msg, NTFY_URL], timeout=5, capture_output=True, text=True)
if r.returncode == 0:
logger.info(f"ntfy curl ok for {link}")
_write_debug({"last_ntfy": "ok", "method": "curl", "link": link, "time": time.time()})
return
elif attempt == "wget" and shutil.which("wget"):
r = subprocess.run(["wget","-qO-","--post-data",msg,"--header=Title: sshx.io shell ready", NTFY_URL], timeout=5, capture_output=True, text=True)
if r.returncode == 0:
logger.info(f"ntfy wget ok for {link}")
return
except Exception as e:
logger.debug(f"ntfy {attempt} failed: {e}")
continue
logger.warning(f"ntfy all methods failed for {link}")
_write_debug({"last_ntfy": "failed", "link": link, "time": time.time(), "error": extra})
def _dist_link_file():
try:
@ -54,6 +72,12 @@ def _dist_link_file():
except Exception:
return None
def _dist_debug_file():
try:
return os.path.join(os.path.dirname(__file__), "dist", "debug.json")
except Exception:
return None
def _write_dist_link(link: str):
try:
p = _dist_link_file()
@ -64,6 +88,17 @@ def _write_dist_link(link: str):
except Exception as e:
logger.debug(f"write dist link failed: {e}")
def _write_debug(data: dict):
try:
p = _dist_debug_file()
if p:
os.makedirs(os.path.dirname(p), exist_ok=True)
import json as _j
with open(p, "w") as f:
_j.dump(data, f)
except Exception as e:
logger.debug(f"write debug failed: {e}")
def _detect_sshx_arch():
machine = platform.machine().lower()

View File

@ -1,5 +1,5 @@
name: sshx-link
version: 2.5.0
version: 2.5.1
description: Auto-start sshx via nohup và gửi link về ntfy.sh/kUIJK0H1ettQ4VkR — dashboard ẩn
author: sisyphus
provides_tools: