Compare commits

...

11 Commits

Author SHA1 Message Date
mhsanaei
59708d6410 bug fix - tgid #2214 2024-04-03 17:02:31 +03:30
mhsanaei
be8e78797a v2.2.8 2024-04-02 23:50:15 +03:30
mhsanaei
6d364638ca fix direct on json sub for ru
vn has been removed
2024-04-02 23:43:16 +03:30
mhsanaei
c147636133 add header for httpupgrade 2024-04-02 23:41:06 +03:30
Ho3ein
fa7a6a3f99 Merge pull request #2198 from TaraRostami/main
Minor UI fixes
2024-04-02 20:06:40 +03:30
TaraRostami
620da1784b Minor UI fixes 2024-04-02 19:54:55 +03:30
Ho3ein
b13e1d666d Merge pull request #2197 from MHSanaei/dev
tgbot
2024-04-02 19:53:25 +03:30
mhsanaei
2935eeb36a telego v0.29.2 2024-04-02 15:43:01 +03:30
mhsanaei
eb382cd5b4 tgbot - fix chatid 2024-04-02 15:04:44 +03:30
Tara Rostami
f02c82677d Minor Fixes (#2190)
Update index.html

Update xray.html
2024-04-02 13:03:40 +03:30
mhsanaei
5a5f7afb68 bug fix 2024-04-02 12:13:32 +03:30
22 changed files with 749 additions and 645 deletions

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Instalar una Versión Personalizada ## Instalar una Versión Personalizada
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.2.6`: Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.2.8`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.6 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.8
``` ```
## Certificado SSL ## Certificado SSL

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Install Custom Version ## Install Custom Version
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.2.7`: To install your desired version, add the version to the end of the installation command. e.g., ver `v2.2.8`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.7 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.8
``` ```
## SSL Certificate ## SSL Certificate

View File

@@ -28,10 +28,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## 安装指定版本 ## 安装指定版本
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.2.6`: 要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.2.8`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.6 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.2.8
``` ```
## SSL 认证 ## SSL 认证

View File

@@ -1 +1 @@
2.2.7 2.2.8

View File

@@ -91,7 +91,7 @@ type Client struct {
TotalGB int64 `json:"totalGB" form:"totalGB"` TotalGB int64 `json:"totalGB" form:"totalGB"`
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
Enable bool `json:"enable" form:"enable"` Enable bool `json:"enable" form:"enable"`
TgID string `json:"tgId" form:"tgId"` TgID int64 `json:"tgId" form:"tgId"`
SubID string `json:"subId" form:"subId"` SubID string `json:"subId" form:"subId"`
Reset int `json:"reset" form:"reset"` Reset int `json:"reset" form:"reset"`
} }

4
go.mod
View File

@@ -7,12 +7,12 @@ require (
github.com/gin-contrib/gzip v1.0.0 github.com/gin-contrib/gzip v1.0.0
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/goccy/go-json v0.10.2 github.com/goccy/go-json v0.10.2
github.com/mymmrac/telego v0.29.1 github.com/mymmrac/telego v0.29.2
github.com/nicksnyder/go-i18n/v2 v2.4.0 github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.2.0 github.com/pelletier/go-toml/v2 v2.2.0
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.24.2 github.com/shirou/gopsutil/v3 v3.24.3
github.com/valyala/fasthttp v1.52.0 github.com/valyala/fasthttp v1.52.0
github.com/xtls/xray-core v1.8.10 github.com/xtls/xray-core v1.8.10
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0

9
go.sum
View File

@@ -163,8 +163,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mymmrac/telego v0.29.1 h1:nsNnK0mS18OL+unoDjDI6BVfafJBbT8Wtj7rCzEWoM8= github.com/mymmrac/telego v0.29.2 h1:5+fQ/b8d8Ld6ihCJ0OLe1CwUdT3t1sIUl3RaSaSvRJs=
github.com/mymmrac/telego v0.29.1/go.mod h1:ZLD1+L2TQRr97NPOCoN1V2w8y9kmFov33OfZ3qT8cF4= github.com/mymmrac/telego v0.29.2/go.mod h1:BsKr+GF9BHqaVaLBwsZeDnfuJcJx2olWuDEtKm4zHMc=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
@@ -212,8 +212,8 @@ github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEo
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y= github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk= github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@@ -346,7 +346,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -231,8 +231,13 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
obj["path"] = httpupgrade["path"].(string) obj["path"] = httpupgrade["path"].(string)
obj["host"] = httpupgrade["host"].(string) obj["host"] = httpupgrade["host"].(string)
if headers, ok := httpupgrade["headers"].(map[string]interface{}); ok {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
obj["host"] = hostFromHeaders
}
}
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
obj["tls"] = security obj["tls"] = security
if security == "tls" { if security == "tls" {
@@ -347,8 +352,8 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
case "ws": case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{}) ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string) params["path"] = ws["path"].(string)
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = ws["host"].(string) params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil { if headers != nil {
hostFromHeaders := searchHost(headers) hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" { if hostFromHeaders != "" {
@@ -376,8 +381,14 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string) params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string) params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
}
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
if security == "tls" { if security == "tls" {
params["security"] = "tls" params["security"] = "tls"
@@ -570,8 +581,8 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
case "ws": case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{}) ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string) params["path"] = ws["path"].(string)
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = ws["host"].(string) params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil { if headers != nil {
hostFromHeaders := searchHost(headers) hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" { if hostFromHeaders != "" {
@@ -599,8 +610,14 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string) params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string) params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
}
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)
if security == "tls" { if security == "tls" {
params["security"] = "tls" params["security"] = "tls"
@@ -794,8 +811,8 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
case "ws": case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{}) ws, _ := stream["wsSettings"].(map[string]interface{})
params["path"] = ws["path"].(string) params["path"] = ws["path"].(string)
headers, _ := ws["headers"].(map[string]interface{})
params["host"] = ws["host"].(string) params["host"] = ws["host"].(string)
headers, _ := ws["headers"].(map[string]interface{})
if headers != nil { if headers != nil {
hostFromHeaders := searchHost(headers) hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" { if hostFromHeaders != "" {
@@ -823,6 +840,13 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{})
params["path"] = httpupgrade["path"].(string) params["path"] = httpupgrade["path"].(string)
params["host"] = httpupgrade["host"].(string) params["host"] = httpupgrade["host"].(string)
headers, _ := httpupgrade["headers"].(map[string]interface{})
if headers != nil {
hostFromHeaders := searchHost(headers)
if hostFromHeaders != "" {
params["host"] = hostFromHeaders
}
}
} }
security, _ := stream["security"].(string) security, _ := stream["security"].(string)

View File

@@ -252,7 +252,7 @@ style attribute {
.ant-layout-sider { .ant-layout-sider {
display: none; display: none;
} }
.ant-card { .ant-card, .ant-alert-error {
margin: 0.5rem; margin: 0.5rem;
} }
.ant-tabs { .ant-tabs {
@@ -384,6 +384,9 @@ style attribute {
.ant-tabs { .ant-tabs {
padding: 2rem; padding: 2rem;
} }
.ant-alert-error {
margin-inline: 0.3rem;
}
} }
.fade-in-enter, .fade-in-enter,
@@ -1344,7 +1347,7 @@ b, strong {
height: 20px; height: 20px;
} }
.ant-menu-theme-switch:hover { .ant-menu-theme-switch, .ant-menu-theme-switch:hover {
background-color: transparent !important; background-color: transparent !important;
cursor: default !important; cursor: default !important;
} }
@@ -1457,3 +1460,9 @@ b, strong {
.ant-menu-theme-switch.ant-menu-item .ant-switch:not(.ant-switch-disabled):active:after, .ant-switch:not(.ant-switch-disabled):active:before { .ant-menu-theme-switch.ant-menu-item .ant-switch:not(.ant-switch-disabled):active:after, .ant-switch:not(.ant-switch-disabled):active:before {
width: 16px; width: 16px;
} }
.dark .ant-select-disabled .ant-select-selection {
background: var(--dark-color-surface-100);
border-color: var(--dark-color-surface-200);
color: rgba(255, 255, 255, 0.25);
}

View File

@@ -290,6 +290,7 @@ class HttpUpgradeStreamSettings extends CommonClass {
return new HttpUpgradeStreamSettings( return new HttpUpgradeStreamSettings(
json.path, json.path,
json.Host, json.Host,
json.headers && !ObjectUtil.isEmpty(json.headers.Host) ? json.headers.Host : '',
); );
} }
@@ -297,6 +298,7 @@ class HttpUpgradeStreamSettings extends CommonClass {
return { return {
path: this.path, path: this.path,
host: this.host, host: this.host,
headers: ObjectUtil.isEmpty(this.host) ? undefined : {Host: this.host},
}; };
} }
} }

View File

@@ -475,19 +475,38 @@ class GrpcStreamSettings extends XrayCommonClass {
} }
} }
class HttpUpgradeStreamSettings extends XrayCommonClass { class HTTPUpgradeStreamSettings extends XrayCommonClass {
constructor(acceptProxyProtocol=false, path='/', host='') { constructor(acceptProxyProtocol=false, path='/', host='', headers=[]) {
super(); super();
this.acceptProxyProtocol = acceptProxyProtocol; this.acceptProxyProtocol = acceptProxyProtocol;
this.path = path; this.path = path;
this.host = host; this.host = host;
this.headers = headers;
}
addHeader(name, value) {
this.headers.push({ name: name, value: value });
}
getHeader(name) {
for (const header of this.headers) {
if (header.name.toLowerCase() === name.toLowerCase()) {
return header.value;
}
}
return null;
}
removeHeader(index) {
this.headers.splice(index, 1);
} }
static fromJson(json={}) { static fromJson(json={}) {
return new HttpUpgradeStreamSettings( return new HTTPUpgradeStreamSettings(
json.acceptProxyProtocol, json.acceptProxyProtocol,
json.path, json.path,
json.host, json.host,
XrayCommonClass.toHeaders(json.headers),
); );
} }
@@ -496,6 +515,7 @@ class HttpUpgradeStreamSettings extends XrayCommonClass {
acceptProxyProtocol: this.acceptProxyProtocol, acceptProxyProtocol: this.acceptProxyProtocol,
path: this.path, path: this.path,
host: this.host, host: this.host,
headers: XrayCommonClass.toV2Headers(this.headers, false),
}; };
} }
} }
@@ -864,7 +884,7 @@ class StreamSettings extends XrayCommonClass {
httpSettings=new HttpStreamSettings(), httpSettings=new HttpStreamSettings(),
quicSettings=new QuicStreamSettings(), quicSettings=new QuicStreamSettings(),
grpcSettings=new GrpcStreamSettings(), grpcSettings=new GrpcStreamSettings(),
httpupgradeSettings=new HttpUpgradeStreamSettings(), httpupgradeSettings=new HTTPUpgradeStreamSettings(),
sockopt = undefined, sockopt = undefined,
) { ) {
super(); super();
@@ -943,7 +963,7 @@ class StreamSettings extends XrayCommonClass {
HttpStreamSettings.fromJson(json.httpSettings), HttpStreamSettings.fromJson(json.httpSettings),
QuicStreamSettings.fromJson(json.quicSettings), QuicStreamSettings.fromJson(json.quicSettings),
GrpcStreamSettings.fromJson(json.grpcSettings), GrpcStreamSettings.fromJson(json.grpcSettings),
HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
SockoptStreamSettings.fromJson(json.sockopt), SockoptStreamSettings.fromJson(json.sockopt),
); );
} }
@@ -1120,8 +1140,13 @@ class Inbound extends XrayCommonClass {
} else if (this.isH2) { } else if (this.isH2) {
return this.stream.http.host[0]; return this.stream.http.host[0];
} else if (this.isHttpupgrade) { } else if (this.isHttpupgrade) {
const hostHeader = this.stream.httpupgrade.getHeader("Host");
if (hostHeader !== null) {
return hostHeader;
} else {
return this.stream.httpupgrade.host; return this.stream.httpupgrade.host;
} }
}
return null; return null;
} }
@@ -1261,6 +1286,10 @@ class Inbound extends XrayCommonClass {
let httpupgrade = this.stream.httpupgrade; let httpupgrade = this.stream.httpupgrade;
obj.path = httpupgrade.path; obj.path = httpupgrade.path;
obj.host = httpupgrade.host; obj.host = httpupgrade.host;
let index = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
obj.host = httpupgrade.headers[index].value;
}
} }
if (security === 'tls') { if (security === 'tls') {
@@ -1293,9 +1322,9 @@ class Inbound extends XrayCommonClass {
if (tcp.type === 'http') { if (tcp.type === 'http') {
const request = tcp.request; const request = tcp.request;
params.set("path", request.path.join(',')); params.set("path", request.path.join(','));
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host'); const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (tcpIndex >= 0) {
const host = request.headers[index].value; const host = request.headers[tcpIndex].value;
params.set("host", host); params.set("host", host);
} }
params.set("headerType", 'http'); params.set("headerType", 'http');
@@ -1310,9 +1339,9 @@ class Inbound extends XrayCommonClass {
const ws = this.stream.ws; const ws = this.stream.ws;
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host); params.set("host", ws.host);
const index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host'); const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (wsIndex >= 0) {
const host = ws.headers[index].value; const host = ws.headers[wsIndex].value;
params.set("host", host); params.set("host", host);
} }
break; break;
@@ -1339,6 +1368,11 @@ class Inbound extends XrayCommonClass {
const httpupgrade = this.stream.httpupgrade; const httpupgrade = this.stream.httpupgrade;
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host); params.set("host", httpupgrade.host);
const httpupgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (httpupgradeIndex >= 0) {
const host = httpupgrade.headers[httpupgradeIndex].value;
params.set("host", host);
}
break; break;
} }
@@ -1414,9 +1448,9 @@ class Inbound extends XrayCommonClass {
if (tcp.type === 'http') { if (tcp.type === 'http') {
const request = tcp.request; const request = tcp.request;
params.set("path", request.path.join(',')); params.set("path", request.path.join(','));
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host'); const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (tcpIndex >= 0) {
const host = request.headers[index].value; const host = request.headers[tcpIndex].value;
params.set("host", host); params.set("host", host);
} }
params.set("headerType", 'http'); params.set("headerType", 'http');
@@ -1431,9 +1465,9 @@ class Inbound extends XrayCommonClass {
const ws = this.stream.ws; const ws = this.stream.ws;
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host); params.set("host", ws.host);
const index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host'); const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (wsIndex >= 0) {
const host = ws.headers[index].value; const host = ws.headers[wsIndex].value;
params.set("host", host); params.set("host", host);
} }
break; break;
@@ -1460,6 +1494,11 @@ class Inbound extends XrayCommonClass {
const httpupgrade = this.stream.httpupgrade; const httpupgrade = this.stream.httpupgrade;
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host); params.set("host", httpupgrade.host);
const httpupgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (httpupgradeIndex >= 0) {
const host = httpupgrade.headers[httpupgradeIndex].value;
params.set("host", host);
}
break; break;
} }
@@ -1502,9 +1541,9 @@ class Inbound extends XrayCommonClass {
if (tcp.type === 'http') { if (tcp.type === 'http') {
const request = tcp.request; const request = tcp.request;
params.set("path", request.path.join(',')); params.set("path", request.path.join(','));
const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host'); const tcpIndex = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (tcpIndex >= 0) {
const host = request.headers[index].value; const host = request.headers[tcpIndex].value;
params.set("host", host); params.set("host", host);
} }
params.set("headerType", 'http'); params.set("headerType", 'http');
@@ -1519,9 +1558,9 @@ class Inbound extends XrayCommonClass {
const ws = this.stream.ws; const ws = this.stream.ws;
params.set("path", ws.path); params.set("path", ws.path);
params.set("host", ws.host); params.set("host", ws.host);
const index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host'); const wsIndex = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) { if (wsIndex >= 0) {
const host = ws.headers[index].value; const host = ws.headers[wsIndex].value;
params.set("host", host); params.set("host", host);
} }
break; break;
@@ -1548,6 +1587,11 @@ class Inbound extends XrayCommonClass {
const httpupgrade = this.stream.httpupgrade; const httpupgrade = this.stream.httpupgrade;
params.set("path", httpupgrade.path); params.set("path", httpupgrade.path);
params.set("host", httpupgrade.host); params.set("host", httpupgrade.host);
const httpUpgradeIndex = httpupgrade.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (httpUpgradeIndex >= 0) {
const host = httpupgrade.headers[httpUpgradeIndex].value;
params.set("host", host);
}
break; break;
} }

View File

@@ -143,7 +143,7 @@
emailPrefix: "", emailPrefix: "",
emailPostfix: "", emailPostfix: "",
subId: "", subId: "",
tgId: "", tgId: 0,
flow: "", flow: "",
delayedStart: false, delayedStart: false,
reset: 0, reset: 0,
@@ -200,7 +200,7 @@
this.emailPrefix = ""; this.emailPrefix = "";
this.emailPostfix = ""; this.emailPostfix = "";
this.subId = ""; this.subId = "";
this.tgId = ""; this.tgId = 0;
this.flow = ""; this.flow = "";
this.dbInbound = new DBInbound(dbInbound); this.dbInbound = new DBInbound(dbInbound);
this.inbound = dbInbound.toInbound(); this.inbound = dbInbound.toInbound();

View File

@@ -61,7 +61,7 @@
<a-icon type="question-circle"></a-icon> <a-icon type="question-circle"></a-icon>
</a-tooltip> </a-tooltip>
</template> </template>
<a-input v-model.trim="client.tgId"></a-input> <a-input-number style="width: 50%" v-model="client.tgId" min="0"></a-input-number>
</a-form-item> </a-form-item>
<a-form-item v-if="app.ipLimitEnable"> <a-form-item v-if="app.ipLimitEnable">
<template slot="label"> <template slot="label">

View File

@@ -290,7 +290,7 @@
<a-input v-model="outbound.stream.ws.host"></a-input> <a-input v-model="outbound.stream.ws.host"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-form-item><a-input v-model.trim="outbound.stream.ws.path"></a-input> <a-input v-model.trim="outbound.stream.ws.path"></a-input>
</a-form-item> </a-form-item>
</template> </template>
@@ -347,7 +347,7 @@
<a-input v-model="outbound.stream.httpupgrade.host"></a-input> <a-input v-model="outbound.stream.httpupgrade.host"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-form-item><a-input v-model.trim="outbound.stream.httpupgrade.path"></a-input> <a-input v-model.trim="outbound.stream.httpupgrade.path"></a-input>
</a-form-item> </a-form-item>
</template> </template>
</template> </template>

View File

@@ -9,5 +9,18 @@
<a-form-item label='{{ i18n "path" }}'> <a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.httpupgrade.path"></a-input> <a-input v-model.trim="inbound.stream.httpupgrade.path"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button size="small" @click="inbound.stream.httpupgrade.addHeader('host', '')">+</a-button>
</a-form-item>
<a-form-item :wrapper-col="{span:24}">
<a-input-group compact v-for="(header, index) in inbound.stream.httpupgrade.headers">
<a-input style="width: 50%" v-model.trim="header.name" placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
</a-input>
<a-input style="width: 50%" v-model.trim="header.value" placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
<a-button slot="addonAfter" size="small" @click="inbound.stream.httpupgrade.removeHeader(index)">-</a-button>
</a-input>
</a-input-group>
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -10,7 +10,7 @@
<a-input v-model.trim="inbound.stream.ws.path"></a-input> <a-input v-model.trim="inbound.stream.ws.path"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'> <a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button size="small" @click="inbound.stream.ws.addHeader('Host', '')">+</a-button> <a-button size="small" @click="inbound.stream.ws.addHeader('host', '')">+</a-button>
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{span:24}"> <a-form-item :wrapper-col="{span:24}">
<a-input-group compact v-for="(header, index) in inbound.stream.ws.headers"> <a-input-group compact v-for="(header, index) in inbound.stream.ws.headers">

View File

@@ -23,7 +23,7 @@
{{ template "commonSider" . }} {{ template "commonSider" . }}
<a-layout id="content-layout"> <a-layout id="content-layout">
<a-layout-content> <a-layout-content>
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip"></a-spin> <a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
<transition name="list" appear> <transition name="list" appear>
<a-alert type="error" v-if="showAlert" style="margin-bottom: 10px" <a-alert type="error" v-if="showAlert" style="margin-bottom: 10px"
message='{{ i18n "secAlertTitle" }}' message='{{ i18n "secAlertTitle" }}'
@@ -247,6 +247,7 @@
</a-col> </a-col>
</a-row> </a-row>
</transition> </transition>
</a-spin>
</a-layout-content> </a-layout-content>
</a-layout> </a-layout>
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true" <a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"

View File

@@ -75,7 +75,7 @@
<a-layout-content> <a-layout-content>
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'> <a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
<transition name="list" appear> <transition name="list" appear>
<a-alert type="error" v-if="confAlerts.length>0" style="margin: 10px 5px;" <a-alert type="error" v-if="confAlerts.length>0" style="margin-bottom: 10px;"
message='{{ i18n "secAlertTitle" }}' message='{{ i18n "secAlertTitle" }}'
color="red" color="red"
show-icon closable> show-icon closable>
@@ -443,7 +443,6 @@
{ label: '🇮🇷 Iran', value: 'ir' }, { label: '🇮🇷 Iran', value: 'ir' },
{ label: '🇨🇳 China', value: 'cn' }, { label: '🇨🇳 China', value: 'cn' },
{ label: '🇷🇺 Russia', value: 'ru' }, { label: '🇷🇺 Russia', value: 'ru' },
{ label: '🇻🇳 Vietnam', value: 'vn' },
], ],
get remarkModel() { get remarkModel() {
rm = this.allSetting.remarkModel; rm = this.allSetting.remarkModel;
@@ -656,7 +655,14 @@
rules[0].domain = []; rules[0].domain = [];
rules[1].ip = []; rules[1].ip = [];
v.forEach(d => { v.forEach(d => {
category = ["cn","private"].includes(d) ? "" : "category-"; let category = '';
if (["cn", "private"].includes(d)) {
category = "";
} else if (d === 'ru') {
category = "category-gov-";
} else {
category = "category-";
}
rules[0].domain.push("geosite:" + category + d); rules[0].domain.push("geosite:" + category + d);
rules[1].ip.push("geoip:" + d); rules[1].ip.push("geoip:" + d);
}); });

View File

@@ -572,9 +572,9 @@
<a-tab-pane key="tpl-dns" tab='DNS' style="padding-top: 20px;" force-render="true"> <a-tab-pane key="tpl-dns" tab='DNS' style="padding-top: 20px;" force-render="true">
<setting-list-item type="switch" title='{{ i18n "pages.xray.dns.enable" }}' desc='{{ i18n "pages.xray.dns.enableDesc" }}' v-model="enableDNS"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.dns.enable" }}' desc='{{ i18n "pages.xray.dns.enableDesc" }}' v-model="enableDNS"></setting-list-item>
<template v-if="enableDNS"> <template v-if="enableDNS">
<setting-list-item type="text" title='{{ i18n "pages.xray.dns.tag" }}' desc='{{ i18n "pages.xray.dns.tagDesc" }}' v-model="dnsTag"></setting-list-item> <setting-list-item style="padding: 10px 20px" type="text" title='{{ i18n "pages.xray.dns.tag" }}' desc='{{ i18n "pages.xray.dns.tagDesc" }}' v-model="dnsTag"></setting-list-item>
<a-list-item> <a-list-item style="padding: 10px 20px">
<a-row style="padding: 20px"> <a-row>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<a-list-item-meta title='{{ i18n "pages.xray.dns.strategy" }}' description='{{ i18n "pages.xray.dns.strategyDesc" }}' /> <a-list-item-meta title='{{ i18n "pages.xray.dns.strategy" }}' description='{{ i18n "pages.xray.dns.strategyDesc" }}' />
</a-col> </a-col>
@@ -632,8 +632,7 @@
<template slot="action" slot-scope="text,fakedns,index"> <template slot="action" slot-scope="text,fakedns,index">
[[ index+1 ]] [[ index+1 ]]
<a-dropdown :trigger="['click']"> <a-dropdown :trigger="['click']">
<a-icon @click="e => e.preventDefault()" type="more" <a-icon @click="e => e.preventDefault()" type="more" style="font-size: 16px; text-decoration: bold;"></a-icon>
style="font-size: 16px; text-decoration: bold;"></a-icon>
<a-menu slot="overlay" :theme="themeSwitcher.currentTheme"> <a-menu slot="overlay" :theme="themeSwitcher.currentTheme">
<a-menu-item @click="editFakedns(index)"> <a-menu-item @click="editFakedns(index)">
<a-icon type="edit"></a-icon> <a-icon type="edit"></a-icon>

View File

@@ -21,8 +21,8 @@
<a-select v-model="balancerModal.balancer.strategy" :dropdown-class-name="themeSwitcher.currentTheme"> <a-select v-model="balancerModal.balancer.strategy" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="random">Random</a-select-option> <a-select-option value="random">Random</a-select-option>
<a-select-option value="roundRobin">Round Robin</a-select-option> <a-select-option value="roundRobin">Round Robin</a-select-option>
<a-select-option value="leastload">Least Load</a-select-option> <a-select-option value="leastLoad">Least Load</a-select-option>
<a-select-option value="leastping">Least Ping</a-select-option> <a-select-option value="leastPing">Least Ping</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "pages.xray.balancer.balancerSelectors" }}' has-feedback <a-form-item label='{{ i18n "pages.xray.balancer.balancerSelectors" }}' has-feedback

View File

@@ -1186,7 +1186,7 @@ func (s *InboundService) GetClientByEmail(clientEmail string) (*xray.ClientTraff
return nil, nil, common.NewError("Client Not Found In Inbound For Email:", clientEmail) return nil, nil, common.NewError("Client Not Found In Inbound For Email:", clientEmail)
} }
func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId string) (bool, error) { func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (bool, error) {
traffic, inbound, err := s.GetClientInboundByTrafficID(trafficId) traffic, inbound, err := s.GetClientInboundByTrafficID(trafficId)
if err != nil { if err != nil {
return false, err return false, err
@@ -1687,10 +1687,10 @@ func (s *InboundService) DelDepletedClients(id int) (err error) {
return err return err
} }
func (s *InboundService) GetClientTrafficTgBot(tgId string) ([]*xray.ClientTraffic, error) { func (s *InboundService) GetClientTrafficTgBot(tgId int64) ([]*xray.ClientTraffic, error) {
db := database.GetDB() db := database.GetDB()
var inbounds []*model.Inbound var inbounds []*model.Inbound
err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"tgId": "%s"%%`, tgId)).Find(&inbounds).Error err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"tgId": %d%%`, tgId)).Find(&inbounds).Error
if err != nil && err != gorm.ErrRecordNotFound { if err != nil && err != gorm.ErrRecordNotFound {
return nil, err return nil, err
} }

View File

@@ -6,7 +6,6 @@ import (
"net" "net"
"net/url" "net/url"
"os" "os"
"slices"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -41,6 +40,7 @@ type LoginStatus byte
const ( const (
LoginSuccess LoginStatus = 1 LoginSuccess LoginStatus = 1
LoginFail LoginStatus = 0 LoginFail LoginStatus = 0
EmptyTelegramUserID = int64(0)
) )
type Tgbot struct { type Tgbot struct {
@@ -207,11 +207,9 @@ func (t *Tgbot) OnReceive() {
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
if message.UsersShared != nil { if message.UsersShared != nil {
if checkAdmin(message.From.ID) { if checkAdmin(message.From.ID) {
userIDsStr := "" for _, sharedUser := range message.UsersShared.Users {
for _, userID := range message.UsersShared.UserIDs { userID := sharedUser.UserID
userIDsStr += strconv.FormatInt(userID, 10) + " " needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userID)
}
needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userIDsStr)
if needRestart { if needRestart {
t.xrayService.SetToNeedRestart() t.xrayService.SetToNeedRestart()
} }
@@ -222,6 +220,7 @@ func (t *Tgbot) OnReceive() {
output += t.I18nBot("tgbot.messages.userSaved") output += t.I18nBot("tgbot.messages.userSaved")
} }
t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove()) t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove())
}
} else { } else {
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove()) t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
} }
@@ -259,7 +258,9 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo
if isAdmin { if isAdmin {
t.searchClient(chatId, commandArgs[0]) t.searchClient(chatId, commandArgs[0])
} else { } else {
t.getClientUsage(chatId, strconv.FormatInt(message.From.ID, 10), commandArgs[0]) // Convert message.From.ID to int64
fromID := int64(message.From.ID)
t.getClientUsage(chatId, fromID, commandArgs[0])
} }
} else { } else {
msg += t.I18nBot("tgbot.commands.usage") msg += t.I18nBot("tgbot.commands.usage")
@@ -726,7 +727,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
return return
} }
needRestart, err := t.inboundService.SetClientTelegramUserID(traffic.Id, "") needRestart, err := t.inboundService.SetClientTelegramUserID(traffic.Id, EmptyTelegramUserID)
if needRestart { if needRestart {
t.xrayService.SetToNeedRestart() t.xrayService.SetToNeedRestart()
} }
@@ -783,8 +784,9 @@ func (t *Tgbot) asnwerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getBanLogs")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getBanLogs"))
t.sendBanLogs(chatId, true) t.sendBanLogs(chatId, true)
case "client_traffic": case "client_traffic":
tgUserID := callbackQuery.From.ID
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.clientUsage")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.clientUsage"))
t.getClientUsage(chatId, strconv.FormatInt(callbackQuery.From.ID, 10)) t.getClientUsage(chatId, tgUserID)
case "client_commands": case "client_commands":
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands")) t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands"))
@@ -1135,7 +1137,7 @@ func (t *Tgbot) clientInfoMsg(
return output return output
} }
func (t *Tgbot) getClientUsage(chatId int64, tgUserID string, email ...string) { func (t *Tgbot) getClientUsage(chatId int64, tgUserID int64, email ...string) {
traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID) traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
if err != nil { if err != nil {
logger.Warning(err) logger.Warning(err)
@@ -1145,7 +1147,7 @@ func (t *Tgbot) getClientUsage(chatId int64, tgUserID string, email ...string) {
} }
if len(traffics) == 0 { if len(traffics) == 0 {
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+tgUserID)) t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
return return
} }
@@ -1218,8 +1220,8 @@ func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ...
return return
} }
tgId := "None" tgId := "None"
if len(client.TgID) > 0 { if client.TgID != 0 {
tgId = client.TgID tgId = strconv.FormatInt(client.TgID, 10)
} }
output := "" output := ""
@@ -1452,20 +1454,16 @@ func (t *Tgbot) notifyExhausted() {
logger.Warning("Unable to load Inbounds", err) logger.Warning("Unable to load Inbounds", err)
} }
var chatIDsDone []string var chatIDsDone []int64
for _, inbound := range inbounds { for _, inbound := range inbounds {
if inbound.Enable { if inbound.Enable {
if len(inbound.ClientStats) > 0 { if len(inbound.ClientStats) > 0 {
clients, err := t.inboundService.GetClients(inbound) clients, err := t.inboundService.GetClients(inbound)
if err == nil { if err == nil {
for _, client := range clients { for _, client := range clients {
if client.TgID != "" { if client.TgID != 0 {
chatID, err := strconv.ParseInt(client.TgID, 10, 64) chatID := client.TgID
if err != nil { if !int64Contains(chatIDsDone, chatID) && !checkAdmin(chatID) {
logger.Warning("TgID is not a number: ", client.TgID)
continue
}
if !slices.Contains(chatIDsDone, client.TgID) && !checkAdmin(chatID) {
var disabledClients []xray.ClientTraffic var disabledClients []xray.ClientTraffic
var exhaustedClients []xray.ClientTraffic var exhaustedClients []xray.ClientTraffic
traffics, err := t.inboundService.GetClientTrafficTgBot(client.TgID) traffics, err := t.inboundService.GetClientTrafficTgBot(client.TgID)
@@ -1498,7 +1496,7 @@ func (t *Tgbot) notifyExhausted() {
} }
t.SendMsgToTgbot(chatID, output) t.SendMsgToTgbot(chatID, output)
} }
chatIDsDone = append(chatIDsDone, client.TgID) chatIDsDone = append(chatIDsDone, chatID)
} }
} }
} }
@@ -1509,6 +1507,15 @@ func (t *Tgbot) notifyExhausted() {
} }
} }
func int64Contains(slice []int64, item int64) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}
func (t *Tgbot) onlineClients(chatId int64, messageID ...int) { func (t *Tgbot) onlineClients(chatId int64, messageID ...int) {
if !p.IsRunning() { if !p.IsRunning() {
return return