diff --git a/database/model/model.go b/database/model/model.go index 047780e59d..3ebfb1cf31 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -135,21 +135,22 @@ type ClientReverse struct { // Client represents a client configuration for Xray inbounds with traffic limits and settings. type Client struct { - ID string `json:"id,omitempty"` // Unique client identifier - Security string `json:"security"` // Security method (e.g., "auto", "aes-128-gcm") - Password string `json:"password,omitempty"` // Client password - Flow string `json:"flow,omitempty"` // Flow control (XTLS) - Reverse *ClientReverse `json:"reverse,omitempty"` // VLESS simple reverse proxy settings - Auth string `json:"auth,omitempty"` // Auth password (Hysteria) - Email string `json:"email"` // Client email identifier - LimitIP int `json:"limitIp"` // IP limit for this client - TotalGB int64 `json:"totalGB" form:"totalGB"` // Total traffic limit in GB - ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` // Expiration timestamp - Enable bool `json:"enable" form:"enable"` // Whether the client is enabled - TgID int64 `json:"tgId" form:"tgId"` // Telegram user ID for notifications - SubID string `json:"subId" form:"subId"` // Subscription identifier - Comment string `json:"comment" form:"comment"` // Client comment - Reset int `json:"reset" form:"reset"` // Reset period in days - CreatedAt int64 `json:"created_at,omitempty"` // Creation timestamp - UpdatedAt int64 `json:"updated_at,omitempty"` // Last update timestamp + ID string `json:"id,omitempty"` // Unique client identifier + Security string `json:"security"` // Security method (e.g., "auto", "aes-128-gcm") + Password string `json:"password,omitempty"` // Client password + Flow string `json:"flow,omitempty"` // Flow control (XTLS) + Auth string `json:"auth,omitempty"` // Auth password (Hysteria) + Email string `json:"email"` // Client email identifier + LimitIP int `json:"limitIp"` // IP limit for this client + UploadSpeedLimit int64 `json:"uploadSpeedLimit" form:"uploadSpeedLimit"` // Upload speed limit in bytes/sec + DownloadSpeedLimit int64 `json:"downloadSpeedLimit" form:"downloadSpeedLimit"` // Download speed limit in bytes/sec + TotalGB int64 `json:"totalGB" form:"totalGB"` // Total traffic limit in GB + ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` // Expiration timestamp + Enable bool `json:"enable" form:"enable"` // Whether the client is enabled + TgID int64 `json:"tgId" form:"tgId"` // Telegram user ID for notifications + SubID string `json:"subId" form:"subId"` // Subscription identifier + Comment string `json:"comment" form:"comment"` // Client comment + Reset int `json:"reset" form:"reset"` // Reset period in days + CreatedAt int64 `json:"created_at,omitempty"` // Creation timestamp + UpdatedAt int64 `json:"updated_at,omitempty"` // Last update timestamp } diff --git a/go.mod b/go.mod index 0a967ebf29..880608387d 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/mhsanaei/3x-ui/v2 go 1.26.3 +replace github.com/xtls/xray-core => ../core + require ( github.com/gin-contrib/gzip v1.2.6 github.com/gin-contrib/sessions v1.1.0 diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js index a3c1d017b1..fd4996f77a 100644 --- a/web/assets/js/model/inbound.js +++ b/web/assets/js/model/inbound.js @@ -2458,6 +2458,8 @@ Inbound.ClientBase = class extends XrayCommonClass { constructor( email = RandomUtil.randomLowerAndNum(8), limitIp = 0, + uploadSpeedLimit = 0, + downloadSpeedLimit = 0, totalGB = 0, expiryTime = 0, enable = true, @@ -2471,6 +2473,8 @@ Inbound.ClientBase = class extends XrayCommonClass { super(); this.email = email; this.limitIp = limitIp; + this.uploadSpeedLimit = uploadSpeedLimit; + this.downloadSpeedLimit = downloadSpeedLimit; this.totalGB = totalGB; this.expiryTime = expiryTime; this.enable = enable; @@ -2486,6 +2490,8 @@ Inbound.ClientBase = class extends XrayCommonClass { return [ json.email, json.limitIp, + json.uploadSpeedLimit, + json.downloadSpeedLimit, json.totalGB, json.expiryTime, json.enable, @@ -2502,6 +2508,8 @@ Inbound.ClientBase = class extends XrayCommonClass { return { email: this.email, limitIp: this.limitIp, + uploadSpeedLimit: this.uploadSpeedLimit, + downloadSpeedLimit: this.downloadSpeedLimit, totalGB: this.totalGB, expiryTime: this.expiryTime, enable: this.enable, @@ -2539,6 +2547,22 @@ Inbound.ClientBase = class extends XrayCommonClass { set _totalGB(gb) { this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0); } + + get _uploadSpeedLimitMB() { + return NumberFormatter.toFixed(this.uploadSpeedLimit / SizeFormatter.ONE_MB, 2); + } + + set _uploadSpeedLimitMB(mb) { + this.uploadSpeedLimit = NumberFormatter.toFixed((mb || 0) * SizeFormatter.ONE_MB, 0); + } + + get _downloadSpeedLimitMB() { + return NumberFormatter.toFixed(this.downloadSpeedLimit / SizeFormatter.ONE_MB, 2); + } + + set _downloadSpeedLimitMB(mb) { + this.downloadSpeedLimit = NumberFormatter.toFixed((mb || 0) * SizeFormatter.ONE_MB, 0); + } }; Inbound.VmessSettings = class extends Inbound.Settings { diff --git a/web/html/form/client.html b/web/html/form/client.html index 737c102e95..352e18de5f 100644 --- a/web/html/form/client.html +++ b/web/html/form/client.html @@ -99,6 +99,35 @@ + + + + MB/s + + + + + MB/s + +