feat(clawbot): add native WeChat ClawBot protocol engine (clawbot.py) and WechatClawModal UI
This commit is contained in:
1 parent
07d2050c5f
commit
8fa46a2b8d
14 files changed
+1551
-201
No files matched your search
@@ -23,6 +23,7 @@ from concurrent.futures import ThreadPoolExecutor
|
|||||||
from http.cookies import SimpleCookie
|
from http.cookies import SimpleCookie
|
||||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from clawbot import ClawBotManager
|
||||||
|
|
||||||
PORT = int(os.environ.get("PORT", "3004"))
|
PORT = int(os.environ.get("PORT", "3004"))
|
||||||
BASE_DIR = Path(__file__).resolve().parent
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
@@ -298,7 +299,9 @@ def collect_telemetry() -> dict:
|
|||||||
"clash": net["router_online"],
|
"clash": net["router_online"],
|
||||||
"router": net["router_online"],
|
"router": net["router_online"],
|
||||||
"uptime": net["azure_online"],
|
"uptime": net["azure_online"],
|
||||||
|
"clawbot": clawbot_mgr.is_connected(),
|
||||||
},
|
},
|
||||||
|
"clawbot": clawbot_mgr.get_public_status(),
|
||||||
}
|
}
|
||||||
with _cache_lock:
|
with _cache_lock:
|
||||||
_cache["data"] = data
|
_cache["data"] = data
|
||||||
@@ -306,6 +309,9 @@ def collect_telemetry() -> dict:
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
clawbot_mgr = ClawBotManager(telemetry_fn=collect_telemetry)
|
||||||
|
|
||||||
|
|
||||||
class PortalHandler(BaseHTTPRequestHandler):
|
class PortalHandler(BaseHTTPRequestHandler):
|
||||||
def log_message(self, fmt, *args):
|
def log_message(self, fmt, *args):
|
||||||
pass
|
pass
|
||||||
@@ -383,6 +389,11 @@ class PortalHandler(BaseHTTPRequestHandler):
|
|||||||
self._send_json(collect_telemetry())
|
self._send_json(collect_telemetry())
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 3b. WeChat ClawBot status endpoint (/api/clawbot/status)
|
||||||
|
if self.path.startswith("/api/clawbot/status"):
|
||||||
|
self._send_json(clawbot_mgr.get_public_status())
|
||||||
|
return
|
||||||
|
|
||||||
# 4. Serve static assets from Vite build output (dist/) if available
|
# 4. Serve static assets from Vite build output (dist/) if available
|
||||||
clean_path = self.path.split("?", 1)[0].lstrip("/")
|
clean_path = self.path.split("?", 1)[0].lstrip("/")
|
||||||
if clean_path and DIST_DIR.exists():
|
if clean_path and DIST_DIR.exists():
|
||||||
@@ -456,6 +467,26 @@ class PortalHandler(BaseHTTPRequestHandler):
|
|||||||
self._send_json({"ok": True}, status=200, extra_headers=headers)
|
self._send_json({"ok": True}, status=200, extra_headers=headers)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 2b. WeChat ClawBot Endpoints (/api/clawbot/*)
|
||||||
|
if self.path == "/api/clawbot/qrcode":
|
||||||
|
res = clawbot_mgr.start_qr_login()
|
||||||
|
self._send_json(res, status=200 if res.get("ok") else 500)
|
||||||
|
return
|
||||||
|
if self.path == "/api/clawbot/verify":
|
||||||
|
length = int(self.headers.get("Content-Length", "0"))
|
||||||
|
raw = self.rfile.read(length).decode("utf-8") if length > 0 else "{}"
|
||||||
|
try:
|
||||||
|
body = json.loads(raw)
|
||||||
|
except Exception:
|
||||||
|
body = {}
|
||||||
|
res = clawbot_mgr.submit_verify_code(str(body.get("code", "")))
|
||||||
|
self._send_json(res)
|
||||||
|
return
|
||||||
|
if self.path == "/api/clawbot/disconnect":
|
||||||
|
res = clawbot_mgr.disconnect()
|
||||||
|
self._send_json(res)
|
||||||
|
return
|
||||||
|
|
||||||
# 3. Operations Actions
|
# 3. Operations Actions
|
||||||
if self.path == "/api/action/backup_nas":
|
if self.path == "/api/action/backup_nas":
|
||||||
out = run_cmd("/Users/ixvii0iv/homelab/scripts/backup-to-nas.sh", timeout=15.0)
|
out = run_cmd("/Users/ixvii0iv/homelab/scripts/backup-to-nas.sh", timeout=15.0)
|
||||||
|
|||||||
Reference in new issue
Block a user