Compare commits

..

10 Commits

Author SHA1 Message Date
心隨緣動
4354efb974
One-click configuration adds protocol combination: VLESS + XHTTP + Reality
Some checks failed
Release X-Panel / Build for Linux (386) (push) Has been cancelled
Release X-Panel / Build for Linux (amd64) (push) Has been cancelled
Release X-Panel / Build for Linux (arm64) (push) Has been cancelled
Release X-Panel / Build for Linux (armv5) (push) Has been cancelled
Release X-Panel / Build for Linux (armv6) (push) Has been cancelled
Release X-Panel / Build for Linux (armv7) (push) Has been cancelled
Release X-Panel / Build for Linux (s390x) (push) Has been cancelled
Release X-Panel / Build for Windows (386) (push) Has been cancelled
Release X-Panel / Build for Windows (amd64) (push) Has been cancelled
2025-10-09 21:47:07 +08:00
心隨緣動
3d4948ce36
v25.10.8 2025-10-08 02:22:10 +08:00
心隨緣動
5e68c54342
v25.10.8 2025-10-08 02:21:47 +08:00
心隨緣動
4bb87ab493
v25.10.8 2025-10-08 00:53:19 +08:00
心隨緣動
92b093b1d0
New features: TG Telegram robot terminal [One-click configuration] and [Subscription conversion] 2025-10-08 00:50:54 +08:00
心隨緣動
f06bb26fc1
New features: TG Telegram robot terminal [One-click configuration] and [Subscription conversion] 2025-10-08 00:45:42 +08:00
心隨緣動
684598a32f
New features: TG Telegram robot terminal [One-click configuration] and [Subscription conversion] 2025-10-08 00:40:13 +08:00
心隨緣動
e19bf6f359 Update some software dependencies 2025-10-07 16:22:15 +00:00
心隨緣動
3834102821
New features: TG Telegram robot terminal [One-click configuration] and [Subscription conversion] 2025-10-08 00:12:40 +08:00
心隨緣動
45e684fe9e
New features: TG Telegram robot terminal [One-click configuration] and [Subscription conversion] 2025-10-08 00:12:34 +08:00
12 changed files with 177 additions and 33 deletions

View File

@ -163,6 +163,12 @@ VERSION=v25.9.20 && bash <(curl -Ls "https://raw.githubusercontent.com/xeefei/x-
![54](./media/54.png)
#### 3、直接复制【链接】导入软件放行【相应端口】去【入站列表】点击【启用】。
![55](./media/55.png)
#### 4、若你是用【TG端电报机器人】的【一键配置】生成功能那直接点击就用
![56](./media/56.png)
#### 5、选择好自己想要【一键创建】的协议组合类型点击之后稍作等待
![57](./media/57.png)
#### 6、TG端【一键配置】创建成功之后二维码和链接地址机器人会发送给你如下
![58](./media/58.png)
------------
## 安装证书开启https方式实现域名登录访问管理面板/----->>偷自己

View File

@ -1 +1 @@
25.9.25
25.10.8

18
go.mod
View File

@ -16,14 +16,15 @@ require (
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.2.4
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.25.8
github.com/shirou/gopsutil/v4 v4.25.9
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/valyala/fasthttp v1.66.0
github.com/xlzd/gotp v0.1.0
github.com/xtls/xray-core v1.250911.0
go.uber.org/atomic v1.11.0
golang.org/x/crypto v0.42.0
golang.org/x/text v0.29.0
google.golang.org/grpc v1.75.1
google.golang.org/grpc v1.76.0
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.0
)
@ -42,7 +43,7 @@ require (
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.27.0 // indirect
github.com/go-playground/validator/v10 v10.28.0 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/gorilla/context v1.1.2 // indirect
@ -67,11 +68,11 @@ require (
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/refraction-networking/utls v1.8.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/sagernet/sing v0.7.10 // indirect
github.com/sagernet/sing v0.7.12 // indirect
github.com/sagernet/sing-shadowsocks v0.2.9 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
@ -85,7 +86,6 @@ require (
github.com/vishvananda/netns v0.0.5 // indirect
github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.6.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/arch v0.21.0 // indirect
golang.org/x/mod v0.28.0 // indirect
@ -96,8 +96,8 @@ require (
golang.org/x/tools v0.37.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect
google.golang.org/protobuf v1.36.9 // indirect
gvisor.dev/gvisor v0.0.0-20250925023741-cd3b33f93629 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251006185510-65f7160b3a87 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gvisor.dev/gvisor v0.0.0-20251007061332-6bf3c4885132 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
)

30
go.sum
View File

@ -46,8 +46,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
@ -126,8 +126,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.54.1 h1:4ZAWm0AhCb6+hE+l5Q1NAL0iRn/ZrMwqHRGQiFwj2eg=
github.com/quic-go/quic-go v0.54.1/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
github.com/refraction-networking/utls v1.8.0 h1:L38krhiTAyj9EeiQQa2sg+hYb4qwLCqdMcpZrRfbONE=
github.com/refraction-networking/utls v1.8.0/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
@ -136,14 +136,16 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sagernet/sing v0.7.10 h1:2yPhZFx+EkyHPH8hXNezgyRSHyGY12CboId7CtwLROw=
github.com/sagernet/sing v0.7.10/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing v0.7.12 h1:MpMbO56crPRZTbltoj1wGk4Xj9+GiwH1wTO4s3fz1EA=
github.com/sagernet/sing v0.7.12/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-shadowsocks v0.2.9 h1:Paep5zCszRKsEn8587O0MnhFWKJwDW1Y4zOYYlIxMkM=
github.com/sagernet/sing-shadowsocks v0.2.9/go.mod h1:TE/Z6401Pi8tgr0nBZcM/xawAI6u3F6TTbz4nH/qw+8=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/shirou/gopsutil/v4 v4.25.8 h1:NnAsw9lN7587WHxjJA9ryDnqhJpFH6A+wagYWTOH970=
github.com/shirou/gopsutil/v4 v4.25.8/go.mod h1:q9QdMmfAOVIw7a+eF86P7ISEU6ka+NLgkUxlopV4RwI=
github.com/shirou/gopsutil/v4 v4.25.9 h1:JImNpf6gCVhKgZhtaAHJ0serfFGtlfIlSC08eaKdTrU=
github.com/shirou/gopsutil/v4 v4.25.9/go.mod h1:gxIxoC+7nQRwUl/xNhutXlD8lq+jxTgpIkEf3rADHL8=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@ -232,12 +234,12 @@ golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+Z
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251006185510-65f7160b3a87 h1:WgGZrMngVRRve7T3P5gbXdmedSmUpkf8uIUu1fg+biY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251006185510-65f7160b3a87/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

BIN
media/56.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
media/57.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
media/58.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -1,4 +1,3 @@
{{ template "page/head_start" .}}
<style>
.ant-table:not(.ant-table-expanded-row .ant-table) {
@ -719,6 +718,9 @@
<a-form-item :label="`{{ i18n "pages.inbounds.oneClick.presetType" }}`">
<a-button @click="handleOneClickOk('vless_reality')" block style="margin-bottom: 10px;" html-type="button">
{{ i18n "pages.inbounds.oneClick.preset.vless_reality" }}
</a-button>
<a-button @click="handleOneClickOk('vless_xhttp_reality')" block style="margin-bottom: 10px;" html-type="button">
{{ i18n "pages.inbounds.oneClick.preset.vless_xhttp_reality" }}
</a-button>
<a-button @click="handleOneClickOk('vless_tls_encryption')" block style="margin-bottom: 10px;" html-type="button">
{{ i18n "pages.inbounds.oneClick.preset.vless_tls_encryption" }}
@ -1294,6 +1296,8 @@ async openPort(port) {
await this.createVlessRealityInbound();
} else if (presetType === 'vless_tls_encryption') {
await this.createVlessTlsEncryptionInbound();
} else if (presetType === 'vless_xhttp_reality') { // 【新增】: 响应新按钮的点击
await this.createVlessXhttpRealityInbound();
} else if (presetType === 'switch') {
this.$message.info('Switch 模式配置尚未实现');
} else {
@ -1579,6 +1583,128 @@ async openPort(port) {
}
},
// 【新增方法】: 创建 VLESS + XHTTP + Reality 入站
async createVlessXhttpRealityInbound() {
try {
// 【中文注释】: 并行请求 Reality 密钥对和 UUID
const [keyPairMsg, uuidMsg] = await Promise.all([
HttpUtil.get('/panel/api/server/getNewX25519Cert'),
HttpUtil.get('/panel/api/server/getNewUUID')
]);
if (!keyPairMsg.success || !keyPairMsg.obj || !uuidMsg.success || !uuidMsg.obj) {
this.$message.error('无法从服务器获取 Reality 密钥对或 UUID请检查后端服务');
return;
}
const { privateKey, publicKey } = keyPairMsg.obj;
const { uuid } = uuidMsg.obj;
// 【中文注释】: 生成随机备注、端口和路径
const remark = Array.from({length: 8}, () => "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[Math.floor(Math.random() * 62)]).join("");
const port = Math.floor(Math.random() * (55535 - 10000 + 1)) + 10000;
const path = "/" + Array.from({ length: 8 }, () => "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)]).join("");
// 【中文注释】: 尝试自动放行端口
const portOpenSuccess = await this.openPort(port);
if (!portOpenSuccess) {
this.$message.warning(`**注意:** 自动放行端口 ${port} 失败,请务必手动到您的 **VPS 防火墙**放行该端口,否则入站将无法连接。`);
}
// 【中文注释】: 随机选择 SNI 和 Short ID
const randomDest = this.realityDestinations[Math.floor(Math.random() * this.realityDestinations.length)];
const randomSni = randomDest.split(':')[0];
const shortIds = this.generateShortIds();
const linkSid = shortIds[Math.floor(Math.random() * shortIds.length)];
// 【中文注释】: 构建发送给后端的入站数据,结构严格按照你提供的 JSON
const data = {
up: 0,
down: 0,
total: 0,
remark: remark,
enable: true,
expiryTime: 0,
deviceLimit: 0,
listen: '',
port: port,
protocol: 'vless',
settings: JSON.stringify({
clients: [{
id: uuid,
flow: "", // 【中文注释】: XHTTP 模式下 flow 为空
email: remark,
level: 0,
password: "",
enable: true
}],
decryption: "none",
selectedAuth: "X25519, not Post-Quantum"
}),
streamSettings: JSON.stringify({
network: "xhttp", // 【中文注释】: 网络模式为 xhttp
security: "reality",
realitySettings: {
show: false,
target: randomDest,
xver: 0,
serverNames: [randomSni, `www.${randomSni}`],
privateKey: privateKey,
maxClientVer: "",
minClientVer: "",
maxTimediff: 0,
mldsa65Seed: "",
shortIds: shortIds,
// 【中文注释】: 请注意 publicKey 现在嵌套在 'settings' 对象中
settings: {
publicKey: publicKey,
spiderX: "/",
mldsa65Verify: ""
}
},
xhttpSettings: {
headers: {},
host: "",
mode: "stream-up",
noSSEHeader: false,
path: path, // 【中文注释】: 使用上面生成的随机路径
scMaxBufferedPosts: 30,
scMaxEachPostBytes: "1000000",
scStreamUpServerSecs: "20-80",
xPaddingBytes: "100-1000"
}
}),
sniffing: JSON.stringify({
enabled: true,
destOverride: ["http", "tls", "quic", "fakedns"],
metadataOnly: false,
routeOnly: false
}),
};
// 【中文注释】: 发送创建请求
const msg = await HttpUtil.post('/panel/api/inbounds/add', data);
if (msg.success) {
// 【中文注释】: 创建成功后,生成正确的分享链接,注意包含 type=xhttp 和 path 参数
const link = `vless://${uuid}@${window.location.hostname}:${port}?type=xhttp&encryption=none&path=${encodeURIComponent(path)}&host=&mode=stream-up&security=reality&pbk=${publicKey}&fp=chrome&sni=${randomSni}&sid=${linkSid}&spx=%2F#${remark}-${remark}`;
this.inboundLink = link;
// 【中文注释】: 显示二维码并保存到历史记录
this.generateOneClickQrCode(link);
this.saveLinkToHistory('vless_xhttp_reality', link); // 【中文注释】: 使用唯一的类型名保存
this.$message.success('VLESS + XHTTP + Reality 配置创建成功!');
await this.getDBInbounds();
} else {
this.$message.error('创建失败: ' + msg.msg);
}
} catch (err) {
console.error("创建 VLESS + XHTTP + Reality 入站时出错:", err);
this.$message.error('创建过程中发生网络错误,请检查后端日志。');
}
},
// 【中文注释】: 这是修复后的 copyLink 方法
async copyLink(linkToCopy) {
const link = linkToCopy || this.inboundLink;

View File

@ -28,6 +28,11 @@ type XrayService struct {
xrayAPI xray.XrayAPI
}
// SetXrayAPI 用于从外部注入 XrayAPI 实例
func (s *XrayService) SetXrayAPI(api xray.XrayAPI) {
s.xrayAPI = api
}
// IsXrayRunning 检查 Xray 是否正在运行
func (s *XrayService) IsXrayRunning() bool {
return p != nil && p.IsRunning()

View File

@ -651,7 +651,7 @@
"status" = "✅ Bot is OK!"
"usage" = "❗ Please provide a text to search!"
"getID" = "🆔 Your ID: <code>{{ .ID }}</code>"
"helpAdminCommands" = "To restart Xray Core:\r\n<code>/restart</code>\r\n\r\nTo search for a client email:\r\n<code>/usage [Email]</code>\r\n\r\nTo search for inbounds (with client stats):\r\n<code>/inbound [Remark]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>"
"helpAdminCommands" = "To restart Xray Core:\r\n<code>/restart</code>\r\n\r\nTo search for customer emails:\r\n<code>/usage [email]</code>\r\n\r\nTo search inbound (with customer statistics):\r\n<code>/inbound [notes]</code>\r\n\r\nTelegram chat ID:\r\n<code>/id</code>\r\n\r\nOne-click configuration:\r\n<code>/oneclick</code>\r\n\r\nSubscription conversion:\r\n<code>/subconverter</code>"
"helpClientCommands" = "To search for statistics, use the following command:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>"
"restartUsage" = "\r\n\r\n<code>/restart</code>"
"restartSuccess" = "✅ Operation successful!"
@ -672,7 +672,7 @@
"datetime" = "⏰ Date&Time: {{ .DateTime }}\r\n"
"hostname" = "💻 Host: {{ .Hostname }}\r\n"
"version" = "🚀 X-Panel Version: v{{ .Version }}\r\n"
"xrayVersion" = "📡 Xray Version: v{{ .XrayVersion }}\r\n"
"xrayVersion" = "📡 Xray Core Version: v{{ .XrayVersion }}\r\n"
"ipv6" = "🌐 IPv6: {{ .IPv6 }}\r\n"
"ipv4" = "🌐 IPv4: {{ .IPv4 }}\r\n"
"ip" = "🌐 IP: {{ .IP }}\r\n"
@ -770,6 +770,8 @@
"change_comment" = "⚙️💬 Comment"
"ResetAllTraffics" = "Reset All Traffics"
"SortedTrafficUsageReport" = "Sorted Traffic Usage Report"
"oneClick" = "🚀 One-click configuration"
"subconverter" = "🔄 Subscription conversion"
[tgbot.answers]
"successfulOperation" = "✅ Operation successful!"

View File

@ -657,7 +657,7 @@
"status" = "✅ 機器人正常運作!"
"usage" = "❗ 請輸入要搜尋的文字!"
"getID" = "🆔 您的 ID 為:<code>{{ .ID }}</code>"
"helpAdminCommands" = "要重新啟動 Xray Core\r\n<code>/restart</code>\r\n\r\n要搜尋客戶電子郵件\r\n<code>/usage [電子郵件]</code>\r\n\r\n要搜尋入站帶有客戶統計資料):\r\n<code>/inbound [備註]</code>\r\n\r\nTelegram 聊天 ID\r\n<code>/id</code>"
"helpAdminCommands" = "要重新啟動 Xray Core\r\n<code>/restart</code>\r\n\n要搜尋客戶電子郵件\r\n<code>/usage [電子郵件]</code>\r\n\r\n要搜尋入站有客戶統計資料):\r\n<code>\r\n\r\n要搜尋入站有客戶統計資料\r\n<code> [備註]</code>\r\n\r\nTelegram聊天ID\r\n<code>/id</code>\r\n\r\n一鍵設定\r\n<code>/oneclick</code>\r\n\r\n訂閱轉換\r\n<code>/subconverter</code>\r\n\r\n訂閱轉換\r\n<code>/subconverter</code>\r\n\r\n訂閱轉換\r\n<code>/subconverter</code>"
"helpClientCommands" = "要搜尋統計資料,請使用以下指令:\r\n<code>/usage [電子郵件]</code>\r\n\r\nTelegram 聊天 ID\r\n<code>/id</code>"
"restartUsage" = "\r\n\r\n<code>/restart</code>"
"restartSuccess" = "✅ 操作成功!"
@ -678,7 +678,7 @@
"datetime" = "⏰ 日期時間:{{ .DateTime }}\r\n"
"hostname" = "💻 主機名稱:{{ .Hostname }}\r\n"
"version" = "🚀 X-Panel 版本v{{ .Version }}\r\n"
"xrayVersion" = "📡 Xray 版本v{{ .XrayVersion }}\r\n"
"xrayVersion" = "📡 Xray Core 版本v{{ .XrayVersion }}\r\n"
"ipv6" = "🌐 IPv6{{ .IPv6 }}\r\n"
"ipv4" = "🌐 IPv4{{ .IPv4 }}\r\n"
"ip" = "🌐 IP{{ .IP }}\r\n"
@ -776,6 +776,8 @@
"change_comment" = "⚙️💬 評論"
"ResetAllTraffics" = "重設所有流量"
"SortedTrafficUsageReport" = "排序的流量使用報告"
"oneClick" = "🚀 一鍵配置"
"subconverter" = "🔄 訂閱轉換"
[tgbot.answers]
"successfulOperation" = "✅ 成功!"

View File

@ -118,7 +118,7 @@ type Server struct {
xrayService service.XrayService
settingService service.SettingService
tgbotService service.Tgbot
tgbotService service.TelegramService
// 〔中文注释〕: 添加这个字段,用来“持有”从 main.go 传递过来的 serverService 实例。
serverService service.ServerService
@ -128,6 +128,7 @@ type Server struct {
cancel context.CancelFunc
}
// 【新增方法】:用于 main.go 将创建好的 tgBotService 注入进来
func (s *Server) SetTelegramService(tgService service.TelegramService) {
s.tgbotService = tgService
@ -477,15 +478,15 @@ func (s *Server) Start() (err error) {
func (s *Server) Stop() error {
s.cancel()
s.xrayService.StopXray()
if s.cron != nil {
s.cron.Stop()
}
// 只有在断言成功后,才能调用只在 *service.Tgbot 上定义的 Stop() 和 IsRunning() 方法。
if tgBot, ok := s.tgbotService.(*service.Tgbot); ok {
if tgBot.IsRunning() {
tgBot.Stop()
}
}
if s.tgbotService.IsRunning() {
s.tgbotService.Stop()
}
var err1 error
var err2 error
if s.httpServer != nil {