67 lines
3.4 KiB
JavaScript
67 lines
3.4 KiB
JavaScript
(function () {
|
|
"use strict";
|
|
const SDK = window.__HERMES_PLUGIN_SDK__;
|
|
const { React } = SDK;
|
|
const { Card, CardHeader, CardTitle, CardContent } = SDK.components;
|
|
|
|
async function fetchJSONAllowError(path) {
|
|
if (SDK && SDK.fetchJSON) {
|
|
try { return await SDK.fetchJSON(path); } catch (e) { if (e && e.data) return e.data; throw e; }
|
|
}
|
|
let url = path;
|
|
try {
|
|
const cur = new URL(window.location.href);
|
|
const profile = cur.searchParams.get("profile");
|
|
if (profile) {
|
|
const u = new URL(path, window.location.origin);
|
|
if (!u.searchParams.get("profile")) u.searchParams.set("profile", profile);
|
|
url = u.pathname + u.search;
|
|
}
|
|
} catch (_) {}
|
|
const res = await fetch(url);
|
|
const text = await res.text();
|
|
try { return JSON.parse(text); } catch (_) { return { status: "error", message: text.slice(0,800) }; }
|
|
}
|
|
|
|
function SSHXPage() {
|
|
const [link, setLink] = React.useState(null);
|
|
const [status, setStatus] = React.useState("idle");
|
|
|
|
const check = React.useCallback(async function(){
|
|
try {
|
|
const r = await fetchJSONAllowError("/api/plugins/sshx-link/status");
|
|
if (r.link) { setLink(r.link); setStatus("running"); }
|
|
else { setLink(null); setStatus(r.status || "stopped"); }
|
|
} catch(_){}
|
|
}, []);
|
|
|
|
React.useEffect(function(){ check(); const t=setInterval(check, 3000); return function(){clearInterval(t);} }, [check]);
|
|
|
|
if (link) {
|
|
return React.createElement(Card, null,
|
|
React.createElement(CardHeader, null,
|
|
React.createElement(CardTitle, null, "sshx.io — Current Link"),
|
|
React.createElement("p", { className:"text-xs text-green-500", style:{fontWeight:600}}, "● Active")
|
|
),
|
|
React.createElement(CardContent, null,
|
|
React.createElement("a", { href: link, target:"_blank", rel:"noopener noreferrer", style:{ color:"#60a5fa", fontSize:"1.05rem", wordBreak:"break-all", textDecoration:"underline", display:"block", fontWeight:600 }}, link),
|
|
React.createElement("p", { className:"text-xs text-muted-foreground", style:{marginTop:"0.5rem"}}, "Link hiện tại của shell sshx. Chỉ hiển thị — không tự chạy nền (hermes kill shell gây lỗi). Chạy thủ công trên host: nohup sshx --quiet > /tmp/sshx_link.txt 2>&1 &")
|
|
)
|
|
);
|
|
}
|
|
return React.createElement(Card, null,
|
|
React.createElement(CardHeader, null,
|
|
React.createElement(CardTitle, null, "sshx.io — Current Link"),
|
|
React.createElement("p", { className:"text-xs text-muted-foreground"}, "Chưa có shell đang chạy")
|
|
),
|
|
React.createElement(CardContent, null,
|
|
React.createElement("p", { className:"text-sm text-muted-foreground"}, "Không có link hiện tại. Plugin ở chế độ passive — không tự chạy sshx nền (hermes kill). Hãy chạy thủ công trên server:"),
|
|
React.createElement("pre", { style:{marginTop:"0.5rem", background:"#111", padding:"0.5rem", borderRadius:"6px", fontSize:"0.75rem", overflow:"auto"}}, "nohup sshx --quiet > /tmp/sshx_link.txt 2>&1 &\ncat /tmp/sshx_link.txt"),
|
|
React.createElement("p", { className:"text-xs text-muted-foreground", style:{marginTop:"0.5rem"}}, "Dashboard sẽ tự đọc /tmp/sshx_link.txt và hiện link ở đây, đồng thời tự refresh mỗi 3s.")
|
|
)
|
|
);
|
|
}
|
|
|
|
window.__HERMES_PLUGINS__.register("sshx-link", SSHXPage);
|
|
})();
|