diff options
| author | lolka1333 <xtrafcyz@gmail.com> | 2026-01-03 07:26:00 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-03 07:26:00 +0300 |
| commit | 313a2acbf66125feb4b145a5636351ed03e666da (patch) | |
| tree | 6be6fac0ced2d0dce60ba55e2feaa83c257ed720 /web/job | |
| parent | b7477302112b43a2ae037b63994c59e85f9c0687 (diff) | |
feat: Add WebSocket support for real-time updates and enhance VLESS settings (#3605)
* feat: add support for trusted X-Forwarded-For and testseed parameters in VLESS settings
* chore: update Xray Core version to 25.12.8 in release workflow
* chore: update Xray Core version to 25.12.8 in Docker initialization script
* chore: bump version to 2.8.6 and add watcher for security changes in inbound modal
* refactor: remove default and random seed buttons from outbound form
* refactor: update VLESS form to rename 'Test Seed' to 'Vision Seed' and change button functionality for seed generation
* refactor: enhance TLS settings form layout with improved button styling and spacing
* feat: integrate WebSocket support for real-time updates on inbounds and Xray service status
* chore: downgrade version to 2.8.5
* refactor: translate comments to English
* fix: ensure testseed is initialized correctly for VLESS protocol and improve client handling in inbound modal
* refactor: simplify VLESS divider condition by removing unnecessary flow checks
* fix: add fallback date formatting for cases when IntlUtil is not available
* refactor: simplify WebSocket message handling by removing batching and ensuring individual message delivery
* refactor: disable WebSocket notifications in inbound and index HTML files
* refactor: enhance VLESS testseed initialization and button functionality in inbound modal
* fix:
* refactor: ensure proper WebSocket URL construction by normalizing basePath
* fix:
* fix:
* fix:
* refactor: update testseed methods for improved reactivity and binding in VLESS form
* logger info to debug
---------
Co-authored-by: lolka1333 <test123@gmail.com>
Diffstat (limited to 'web/job')
| -rw-r--r-- | web/job/ldap_sync_job.go | 60 | ||||
| -rw-r--r-- | web/job/xray_traffic_job.go | 18 |
2 files changed, 18 insertions, 60 deletions
diff --git a/web/job/ldap_sync_job.go b/web/job/ldap_sync_job.go index 6642bbcf..a947eb73 100644 --- a/web/job/ldap_sync_job.go +++ b/web/job/ldap_sync_job.go @@ -322,66 +322,6 @@ func (j *LdapSyncJob) clientsToJSON(clients []model.Client) string { return b.String() } -// ensureClientExists adds client with defaults to inbound tag if not present -func (j *LdapSyncJob) ensureClientExists(inboundTag string, email string, defGB int, defExpiryDays int, defLimitIP int) { - inbounds, err := j.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("ensureClientExists: get inbounds failed:", err) - return - } - var target *model.Inbound - for _, ib := range inbounds { - if ib.Tag == inboundTag { - target = ib - break - } - } - if target == nil { - logger.Debugf("ensureClientExists: inbound tag %s not found", inboundTag) - return - } - // check if email already exists in this inbound - clients, err := j.inboundService.GetClients(target) - if err == nil { - for _, c := range clients { - if c.Email == email { - return - } - } - } - - // build new client according to protocol - newClient := model.Client{ - Email: email, - Enable: true, - LimitIP: defLimitIP, - TotalGB: int64(defGB), - } - if defExpiryDays > 0 { - newClient.ExpiryTime = time.Now().Add(time.Duration(defExpiryDays) * 24 * time.Hour).UnixMilli() - } - - switch target.Protocol { - case model.Trojan: - newClient.Password = uuid.NewString() - case model.Shadowsocks: - newClient.Password = uuid.NewString() - default: // VMESS/VLESS and others using ID - newClient.ID = uuid.NewString() - } - - // prepare inbound payload with only the new client - payload := &model.Inbound{Id: target.Id} - payload.Settings = `{"clients":[` + j.clientToJSON(newClient) + `]}` - - if _, err := j.inboundService.AddInboundClient(payload); err != nil { - logger.Warning("ensureClientExists: add client failed:", err) - } else { - j.xrayService.SetToNeedRestart() - logger.Infof("LDAP auto-create: %s in %s", email, inboundTag) - } -} - // clientToJSON serializes minimal client fields to JSON object string without extra deps func (j *LdapSyncJob) clientToJSON(c model.Client) string { // construct minimal JSON manually to avoid importing json for simple case diff --git a/web/job/xray_traffic_job.go b/web/job/xray_traffic_job.go index a9affb4b..2f331cd6 100644 --- a/web/job/xray_traffic_job.go +++ b/web/job/xray_traffic_job.go @@ -5,6 +5,7 @@ import ( "github.com/mhsanaei/3x-ui/v2/logger" "github.com/mhsanaei/3x-ui/v2/web/service" + "github.com/mhsanaei/3x-ui/v2/web/websocket" "github.com/mhsanaei/3x-ui/v2/xray" "github.com/valyala/fasthttp" @@ -48,6 +49,23 @@ func (j *XrayTrafficJob) Run() { if needRestart0 || needRestart1 { j.xrayService.SetToNeedRestart() } + + // Get online clients and last online map for real-time status updates + onlineClients := j.inboundService.GetOnlineClients() + lastOnlineMap, err := j.inboundService.GetClientsLastOnline() + if err != nil { + logger.Warning("get clients last online failed:", err) + lastOnlineMap = make(map[string]int64) + } + + // Broadcast traffic update via WebSocket + trafficUpdate := map[string]interface{}{ + "traffics": traffics, + "clientTraffics": clientTraffics, + "onlineClients": onlineClients, + "lastOnlineMap": lastOnlineMap, + } + websocket.BroadcastTraffic(trafficUpdate) } func (j *XrayTrafficJob) informTrafficToExternalAPI(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) { |
