Compare commits

...

9 Commits
1.0.0 ... 1.0.1

Author SHA1 Message Date
Alireza Ahmadi
4838b0f6f0 v1.0.1 2023-04-20 14:30:58 +02:00
Alireza Ahmadi
bb8807129a [client] add reset traffic in edit #244 2023-04-20 13:59:32 +02:00
Alireza Ahmadi
cb050bfe34 [sub] fix userinfo header #217 2023-04-20 12:53:50 +02:00
Alireza Ahmadi
76a996cc2d main.go enhancements 2023-04-20 10:55:58 +02:00
Alireza Ahmadi
7fec1dd5cf [reality] fix fingerprint issue #236 2023-04-20 10:50:20 +02:00
Alireza Ahmadi
a24e9089b6 small visual enhancements #237 2023-04-20 10:48:57 +02:00
Alireza Ahmadi
b6474eaef6 fix setting numbers #237 2023-04-20 10:47:24 +02:00
Alireza Ahmadi
76f90b0a46 fix enabletgbot cli 2023-04-20 10:45:21 +02:00
Alireza Ahmadi
42abffdaef [docker] fix build for amd64 2023-04-20 10:36:46 +02:00
13 changed files with 55 additions and 46 deletions

View File

@@ -10,8 +10,11 @@ else
FNAME="amd64"; FNAME="amd64";
fi fi
mkdir -p build/bin mkdir -p build/bin
cd build/bin
wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.1/Xray-linux-${ARCH}.zip" wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.1/Xray-linux-${ARCH}.zip"
wget "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" -o build/bin/geoip.dat unzip "Xray-linux-${ARCH}.zip"
wget "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" -o build/bin/geosite.dat rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
mv xray "build/bin/xray-linux-${FNAME}" mv xray "xray-linux-${FNAME}"
mv main build/x-ui wget "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat"
wget "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat"
cd ../../

View File

@@ -1,9 +1,9 @@
FROM golang:1.20-alpine AS builder FROM golang:1.20-alpine AS builder
WORKDIR /app WORKDIR /app
ARG TARGETARCH ARG TARGETARCH
RUN apk --no-cache --update add build-base gcc wget RUN apk --no-cache --update add build-base gcc wget unzip
COPY . . COPY . .
RUN env CGO_ENABLED=1 go build main.go RUN env CGO_ENABLED=1 go build -o build/x-ui main.go
RUN ./DockerInitFiles.sh "$TARGETARCH" RUN ./DockerInitFiles.sh "$TARGETARCH"
FROM alpine FROM alpine

View File

@@ -1 +1 @@
1.0.0 1.0.1

View File

@@ -51,8 +51,8 @@ func runWebServer() {
} }
sigCh := make(chan os.Signal, 1) sigCh := make(chan os.Signal, 1)
//信号量捕获处理 // Trap shutdown signals
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGKILL) signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM)
for { for {
sig := <-sigCh sig := <-sigCh
@@ -133,7 +133,6 @@ func updateTgbotEnableSts(status bool) {
logger.Infof("SetTgbotenabled[%v] success", status) logger.Infof("SetTgbotenabled[%v] success", status)
} }
} }
return
} }
func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) { func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime string) {
@@ -290,6 +289,9 @@ func main() {
if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") { if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") {
updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime) updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime)
} }
if enabletgbot {
updateTgbotEnableSts(enabletgbot)
}
default: default:
fmt.Println("except 'run' or 'v2-ui' or 'setting' subcommands") fmt.Println("except 'run' or 'v2-ui' or 'setting' subcommands")
fmt.Println() fmt.Println()

View File

@@ -647,7 +647,7 @@ class RealityStreamSettings extends XrayCommonClass {
} }
RealityStreamSettings.Settings = class extends XrayCommonClass { RealityStreamSettings.Settings = class extends XrayCommonClass {
constructor(publicKey = '', fingerprint = '', serverName = '', spiderX= '/') { constructor(publicKey = '', fingerprint = UTLS_FINGERPRINT.UTLS_FIREFOX, serverName = '', spiderX= '/') {
super(); super();
this.publicKey = publicKey; this.publicKey = publicKey;
this.fingerprint = fingerprint; this.fingerprint = fingerprint;
@@ -1243,15 +1243,13 @@ class Inbound extends XrayCommonClass {
if (this.reality) { if (this.reality) {
params.set("security", "reality"); params.set("security", "reality");
params.set("pbk", this.stream.reality.settings.publicKey); params.set("pbk", this.stream.reality.settings.publicKey);
params.set("fp", this.stream.reality.settings.fingerprint);
if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) { if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) {
params.set("sni", this.stream.reality.serverNames.split(",")[0]); params.set("sni", this.stream.reality.serverNames.split(",")[0]);
} }
if (this.stream.reality.shortIds.length > 0) { if (this.stream.reality.shortIds.length > 0) {
params.set("sid", this.stream.reality.shortIds.split(",")[0]); params.set("sid", this.stream.reality.shortIds.split(",")[0]);
} }
if (!ObjectUtil.isEmpty(this.stream.reality.fingerprint)) {
params.set("fp", this.stream.reality.settings.fingerprint);
}
if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) {
address = this.stream.reality.settings.serverName; address = this.stream.reality.settings.serverName;
} }
@@ -1355,15 +1353,13 @@ class Inbound extends XrayCommonClass {
if (this.reality) { if (this.reality) {
params.set("security", "reality"); params.set("security", "reality");
params.set("pbk", this.stream.reality.settings.publicKey); params.set("pbk", this.stream.reality.settings.publicKey);
params.set("fp", this.stream.reality.settings.fingerprint);
if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) { if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) {
params.set("sni", this.stream.reality.serverNames.split(",")[0]); params.set("sni", this.stream.reality.serverNames.split(",")[0]);
} }
if (this.stream.reality.shortIds.length > 0) { if (this.stream.reality.shortIds.length > 0) {
params.set("sid", this.stream.reality.shortIds.split(",")[0]); params.set("sid", this.stream.reality.shortIds.split(",")[0]);
} }
if (!ObjectUtil.isEmpty(this.stream.reality.fingerprint)) {
params.set("fp", this.stream.reality.settings.fingerprint);
}
if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) {
address = this.stream.reality.settings.serverName; address = this.stream.reality.settings.serverName;
} }

View File

@@ -39,7 +39,7 @@ func (a *SUBController) subs(c *gin.Context) {
} }
// Add subscription-userinfo // Add subscription-userinfo
c.Writer.Header().Set("subscription-userinfo", header) c.Writer.Header().Set("Subscription-Userinfo", header)
c.String(200, base64.StdEncoding.EncodeToString([]byte(result))) c.String(200, base64.StdEncoding.EncodeToString([]byte(result)))
} }

View File

@@ -122,6 +122,24 @@
} }
client.email = string; client.email = string;
}, },
resetClientTraffic(email,dbInboundId,iconElement) {
this.$confirm({
title: '{{ i18n "pages.inbounds.resetTraffic"}}',
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
class: siderDrawer.isDarkTheme ? darkClass : '',
okText: '{{ i18n "reset"}}',
cancelText: '{{ i18n "cancel"}}',
onOk: async () => {
iconElement.disabled = true;
const msg = await HttpUtil.postWithModal('/xui/inbound/' + dbInboundId + '/resetClientTraffic/'+ email);
if (msg.success) {
this.clientModal.clientStats.up = 0;
this.clientModal.clientStats.down = 0;
}
iconElement.disabled = false;
},
})
},
}, },
}); });
</script> </script>

View File

@@ -9,7 +9,7 @@
<a-input :value="value" @input="$emit('input', $event.target.value)"></a-input> <a-input :value="value" @input="$emit('input', $event.target.value)"></a-input>
</template> </template>
<template v-else-if="type === 'number'"> <template v-else-if="type === 'number'">
<a-input-number :value="value" @input="$emit('input', $event.target.value)"></a-input-number> <a-input type="number" :value="value" @input="$emit('input', $event.target.value)"></a-input>
</template> </template>
<template v-else-if="type === 'textarea'"> <template v-else-if="type === 'textarea'">
<a-textarea :value="value" @input="$emit('input', $event.target.value)" :auto-size="{ minRows: 10, maxRows: 10 }"></a-textarea> <a-textarea :value="value" @input="$emit('input', $event.target.value)" :auto-size="{ minRows: 10, maxRows: 10 }"></a-textarea>

View File

@@ -103,6 +103,10 @@
[[ sizeFormat(clientStats.down) ]] [[ sizeFormat(clientStats.down) ]]
([[ sizeFormat(clientStats.up + clientStats.down) ]]) ([[ sizeFormat(clientStats.up + clientStats.down) ]])
</a-tag> </a-tag>
<a-tooltip>
<template slot="title">{{ i18n "pages.inbounds.resetTraffic" }}</template>
<a-icon type="retweet" @click="resetClientTraffic(client.email,clientStats.inboundId,$event.target)" v-if="client.email.length > 0"></a-icon>
</a-tooltip>
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@@ -1,24 +1,17 @@
{{define "form/streamSettings"}} {{define "form/streamSettings"}}
<!-- select stream network --> <!-- select stream network -->
<a-form layout="inline"> <a-form layout="inline">
<table width="100%" class="ant-table-tbody"> <a-form-item label="{{ i18n "transmission" }}">
<tr> <a-select v-model="inbound.stream.network" @change="streamNetworkChange"
<td>{{ i18n "transmission" }}</td> :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''">
<td> <a-select-option value="tcp">tcp</a-select-option>
<a-form-item> <a-select-option value="kcp">kcp</a-select-option>
<a-select v-model="inbound.stream.network" @change="streamNetworkChange" <a-select-option value="ws">ws</a-select-option>
:dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> <a-select-option value="http">http</a-select-option>
<a-select-option value="tcp">tcp</a-select-option> <a-select-option value="quic">quic</a-select-option>
<a-select-option value="kcp">kcp</a-select-option> <a-select-option value="grpc">grpc</a-select-option>
<a-select-option value="ws">ws</a-select-option> </a-select>
<a-select-option value="http">http</a-select-option> </a-form-item>
<a-select-option value="quic">quic</a-select-option>
<a-select-option value="grpc">grpc</a-select-option>
</a-select>
</a-form-item>
</td>
</tr>
</table>
</a-form> </a-form>
<!-- tcp --> <!-- tcp -->

View File

@@ -176,7 +176,6 @@
<td> <td>
<a-form-item > <a-form-item >
<a-select v-model="inbound.stream.reality.settings.fingerprint" style="width: 250px"> <a-select v-model="inbound.stream.reality.settings.fingerprint" style="width: 250px">
<a-select-option value=''>None</a-select-option>
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>

View File

@@ -51,7 +51,7 @@
</td> </td>
<td v-else-if="inbound.reality"> <td v-else-if="inbound.reality">
reality: <a-tag color="green">{{ i18n "enabled" }}</a-tag><br /> reality: <a-tag color="green">{{ i18n "enabled" }}</a-tag><br />
reality {{ i18n "domainName" }}: <a-tag :color="inbound.serverName ? 'green' : 'orange'">[[ inbound.serverName ? inbound.serverName : '' ]]</a-tag> reality Destination: <a-tag :color="inbound.stream.reality.dest ? 'green' : 'orange'">[[ inbound.stream.reality.dest ]]</a-tag>
</td> </td>
<td v-else>tls: <a-tag color="red">{{ i18n "disabled" }}</a-tag> <td v-else>tls: <a-tag color="red">{{ i18n "disabled" }}</a-tag>
</td> </td>

View File

@@ -66,13 +66,7 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, string, error
} }
} }
} }
header = fmt.Sprintf("upload=%d;download=%d", traffic.Up, traffic.Down) header = fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000)
if traffic.Total > 0 {
header = header + fmt.Sprintf(";total=%d", traffic.Total)
}
if traffic.ExpiryTime > 0 {
header = header + fmt.Sprintf(";expire=%d", traffic.ExpiryTime)
}
return result, header, nil return result, header, nil
} }