From 3ed6d368b664a5db687e0dc9025c00a3a2825d60 Mon Sep 17 00:00:00 2001 From: lolka1333 Date: Sun, 14 Dec 2025 09:18:38 +0100 Subject: [PATCH] feat: integrate WebSocket support for real-time updates on inbounds and Xray service status --- go.mod | 2 +- web.rar | Bin 0 -> 2308946 bytes web/assets/js/websocket.js | 138 +++++++++++ web/controller/inbound.go | 12 + web/controller/server.go | 17 ++ web/controller/websocket.go | 232 ++++++++++++++++++ web/global/global.go | 1 + web/html/common/page.html | 1 + web/html/form/protocol/vless.html | 1 + web/html/inbounds.html | 96 +++++++- web/html/index.html | 82 ++++++- web/job/ldap_sync_job.go | 60 ----- web/job/xray_traffic_job.go | 18 ++ web/web.go | 22 ++ web/websocket/hub.go | 379 ++++++++++++++++++++++++++++++ web/websocket/notifier.go | 74 ++++++ 16 files changed, 1061 insertions(+), 74 deletions(-) create mode 100644 web.rar create mode 100644 web/assets/js/websocket.js create mode 100644 web/controller/websocket.go create mode 100644 web/websocket/hub.go create mode 100644 web/websocket/notifier.go diff --git a/go.mod b/go.mod index 2f81efb8..ab54cbaf 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-ldap/ldap/v3 v3.4.12 github.com/goccy/go-json v0.10.5 github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.3 github.com/joho/godotenv v1.5.1 github.com/mymmrac/telego v1.3.1 github.com/nicksnyder/go-i18n/v2 v2.6.0 @@ -51,7 +52,6 @@ require ( github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.4.0 // indirect - github.com/gorilla/websocket v1.5.3 // indirect github.com/grbit/go-json v0.11.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect diff --git a/web.rar b/web.rar new file mode 100644 index 0000000000000000000000000000000000000000..8e3093b7afbedd36df7f3cdfacf015a6fa3300d4 GIT binary patch literal 2308946 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