Skip to content

Commit 1bbf31d

Browse files
AliAkhgarrootroot
authored
feat(externalTrafficJob): External Traffic Inform (#2660)
* Add Setting entity + GUI field in panel settings * Add a missing 'Traffic' in InformEnabale field * Add ExternalTrafficURL Post request call * Add translation + cleanup * Move options to General tab --------- Co-authored-by: root <root@vm3562019.stark-industries.solutions> Co-authored-by: root <root@vm3688062.stark-industries.solutions>
1 parent 49bfff9 commit 1bbf31d

17 files changed

+145
-42
lines changed

web/assets/js/model/setting.js

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class AllSetting {
3131
this.subPath = "/sub/";
3232
this.subJsonPath = "/json/";
3333
this.subDomain = "";
34+
this.externalTrafficInformEnable = false;
35+
this.externalTrafficInformURI = "";
3436
this.subCertFile = "";
3537
this.subKeyFile = "";
3638
this.subUpdates = 12;

web/entity/entity.go

+43-41
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,49 @@ type Msg struct {
1616
}
1717

1818
type AllSetting struct {
19-
WebListen string `json:"webListen" form:"webListen"`
20-
WebDomain string `json:"webDomain" form:"webDomain"`
21-
WebPort int `json:"webPort" form:"webPort"`
22-
WebCertFile string `json:"webCertFile" form:"webCertFile"`
23-
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
24-
WebBasePath string `json:"webBasePath" form:"webBasePath"`
25-
SessionMaxAge int `json:"sessionMaxAge" form:"sessionMaxAge"`
26-
PageSize int `json:"pageSize" form:"pageSize"`
27-
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
28-
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
29-
RemarkModel string `json:"remarkModel" form:"remarkModel"`
30-
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
31-
TgBotToken string `json:"tgBotToken" form:"tgBotToken"`
32-
TgBotProxy string `json:"tgBotProxy" form:"tgBotProxy"`
33-
TgBotAPIServer string `json:"tgBotAPIServer" form:"tgBotAPIServer"`
34-
TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"`
35-
TgRunTime string `json:"tgRunTime" form:"tgRunTime"`
36-
TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"`
37-
TgBotLoginNotify bool `json:"tgBotLoginNotify" form:"tgBotLoginNotify"`
38-
TgCpu int `json:"tgCpu" form:"tgCpu"`
39-
TgLang string `json:"tgLang" form:"tgLang"`
40-
TimeLocation string `json:"timeLocation" form:"timeLocation"`
41-
SecretEnable bool `json:"secretEnable" form:"secretEnable"`
42-
SubEnable bool `json:"subEnable" form:"subEnable"`
43-
SubListen string `json:"subListen" form:"subListen"`
44-
SubPort int `json:"subPort" form:"subPort"`
45-
SubPath string `json:"subPath" form:"subPath"`
46-
SubDomain string `json:"subDomain" form:"subDomain"`
47-
SubCertFile string `json:"subCertFile" form:"subCertFile"`
48-
SubKeyFile string `json:"subKeyFile" form:"subKeyFile"`
49-
SubUpdates int `json:"subUpdates" form:"subUpdates"`
50-
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
51-
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
52-
SubURI string `json:"subURI" form:"subURI"`
53-
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
54-
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
55-
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
56-
SubJsonNoises string `json:"subJsonNoises" form:"subJsonNoises"`
57-
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
58-
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
59-
Datepicker string `json:"datepicker" form:"datepicker"`
19+
WebListen string `json:"webListen" form:"webListen"`
20+
WebDomain string `json:"webDomain" form:"webDomain"`
21+
WebPort int `json:"webPort" form:"webPort"`
22+
WebCertFile string `json:"webCertFile" form:"webCertFile"`
23+
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
24+
WebBasePath string `json:"webBasePath" form:"webBasePath"`
25+
SessionMaxAge int `json:"sessionMaxAge" form:"sessionMaxAge"`
26+
PageSize int `json:"pageSize" form:"pageSize"`
27+
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
28+
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
29+
RemarkModel string `json:"remarkModel" form:"remarkModel"`
30+
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
31+
TgBotToken string `json:"tgBotToken" form:"tgBotToken"`
32+
TgBotProxy string `json:"tgBotProxy" form:"tgBotProxy"`
33+
TgBotAPIServer string `json:"tgBotAPIServer" form:"tgBotAPIServer"`
34+
TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"`
35+
TgRunTime string `json:"tgRunTime" form:"tgRunTime"`
36+
TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"`
37+
TgBotLoginNotify bool `json:"tgBotLoginNotify" form:"tgBotLoginNotify"`
38+
TgCpu int `json:"tgCpu" form:"tgCpu"`
39+
TgLang string `json:"tgLang" form:"tgLang"`
40+
TimeLocation string `json:"timeLocation" form:"timeLocation"`
41+
SecretEnable bool `json:"secretEnable" form:"secretEnable"`
42+
SubEnable bool `json:"subEnable" form:"subEnable"`
43+
SubListen string `json:"subListen" form:"subListen"`
44+
SubPort int `json:"subPort" form:"subPort"`
45+
SubPath string `json:"subPath" form:"subPath"`
46+
SubDomain string `json:"subDomain" form:"subDomain"`
47+
SubCertFile string `json:"subCertFile" form:"subCertFile"`
48+
SubKeyFile string `json:"subKeyFile" form:"subKeyFile"`
49+
SubUpdates int `json:"subUpdates" form:"subUpdates"`
50+
ExternalTrafficInformEnable bool `json:"externalTrafficInformEnable" form:"externalTrafficInformEnable"`
51+
ExternalTrafficInformURI string `json:"externalTrafficInformURI" form:"externalTrafficInformURI"`
52+
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
53+
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
54+
SubURI string `json:"subURI" form:"subURI"`
55+
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
56+
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
57+
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
58+
SubJsonNoises string `json:"subJsonNoises" form:"subJsonNoises"`
59+
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
60+
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
61+
Datepicker string `json:"datepicker" form:"datepicker"`
6062
}
6163

6264
func (s *AllSetting) CheckValid() error {

web/html/xui/settings.html

+2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@
142142
<setting-list-item type="number" title='{{ i18n "pages.settings.pageSize" }}' desc='{{ i18n "pages.settings.pageSizeDesc" }}' v-model="allSetting.pageSize" :min="0" :step="5"></setting-list-item>
143143
<setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
144144
<setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
145+
<setting-list-item type="switch" title='{{ i18n "pages.settings.externalTrafficInformEnable"}}' desc='{{ i18n "pages.settings.externalTrafficInformEnableDesc"}}' v-model="allSetting.externalTrafficInformEnable"></setting-list-item>
146+
<setting-list-item type="text" title='{{ i18n "pages.settings.externalTrafficInformURI"}}' desc='{{ i18n "pages.settings.externalTrafficInformURIDesc"}}' v-model="allSetting.externalTrafficInformURI" placeholder="(http|https)://domain[:port]/path/"></setting-list-item>
145147
<setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
146148
<a-list-item>
147149
<a-row style="padding: 20px">

web/job/xray_traffic_job.go

+34
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package job
22

33
import (
4+
"encoding/json"
45
"x-ui/logger"
56
"x-ui/web/service"
7+
"x-ui/xray"
8+
9+
"github.com/valyala/fasthttp"
610
)
711

812
type XrayTrafficJob struct {
13+
settingService service.SettingService
914
xrayService service.XrayService
1015
inboundService service.InboundService
1116
outboundService service.OutboundService
@@ -31,7 +36,36 @@ func (j *XrayTrafficJob) Run() {
3136
if err != nil {
3237
logger.Warning("add outbound traffic failed:", err)
3338
}
39+
if ExternalTrafficInformEnable, err := j.settingService.GetExternalTrafficInformEnable(); ExternalTrafficInformEnable {
40+
j.informTrafficToExternalAPI(traffics, clientTraffics)
41+
} else if err != nil {
42+
logger.Warning("get ExternalTrafficInformEnable failed:", err)
43+
}
3444
if needRestart0 || needRestart1 {
3545
j.xrayService.SetToNeedRestart()
3646
}
3747
}
48+
49+
func (j *XrayTrafficJob) informTrafficToExternalAPI(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) {
50+
informURL, err := j.settingService.GetExternalTrafficInformURI()
51+
if err != nil {
52+
logger.Warning("get ExternalTrafficInformURI failed:", err)
53+
return
54+
}
55+
requestBody, err := json.Marshal(map[string]interface{}{"clientTraffics": clientTraffics, "inboundTraffics": inboundTraffics})
56+
if err != nil {
57+
logger.Warning("parse client/inbound traffic failed:", err)
58+
return
59+
}
60+
request := fasthttp.AcquireRequest()
61+
defer fasthttp.ReleaseRequest(request)
62+
request.Header.SetMethod("POST")
63+
request.Header.SetContentType("application/json; charset=UTF-8")
64+
request.SetBody([]byte(requestBody))
65+
request.SetRequestURI(informURL)
66+
response := fasthttp.AcquireResponse()
67+
defer fasthttp.ReleaseResponse(response)
68+
if err := fasthttp.Do(request, response); err != nil {
69+
logger.Warning("POST ExternalTrafficInformURI failed:", err)
70+
}
71+
}

web/service/setting.go

+16
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,22 @@ func (s *SettingService) SetWarp(data string) error {
496496
return s.setString("warp", data)
497497
}
498498

499+
func (s *SettingService) GetExternalTrafficInformEnable() (bool, error) {
500+
return s.getBool("externalTrafficInformEnable")
501+
}
502+
503+
func (s *SettingService) SetExternalTrafficInformEnable(value bool) error {
504+
return s.setBool("externalTrafficInformEnable", value)
505+
}
506+
507+
func (s *SettingService) GetExternalTrafficInformURI() (string, error) {
508+
return s.getString("externalTrafficInformURI")
509+
}
510+
511+
func (s *SettingService) SetExternalTrafficInformURI(InformURI string) error {
512+
return s.setString("externalTrafficInformURI", InformURI)
513+
}
514+
499515
func (s *SettingService) GetIpLimitEnable() (bool, error) {
500516
accessLogPath, err := xray.GetAccessLogPath()
501517
if err != nil {

web/translation/translate.en_US.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "The remaining traffic and date will be displayed in the client apps."
308308
"subURI" = "Reverse Proxy URI"
309309
"subURIDesc" = "The URI path of the subscription URL for use behind proxies."
310+
"externalTrafficInformEnable" = "External Traffic Inform"
311+
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
312+
"externalTrafficInformURI" = "External Traffic Inform URI"
313+
"externalTrafficInformURIDesc" = "Traffic updates are sent to this URI."
310314
"fragment" = "Fragmentation"
311315
"fragmentDesc" = "Enable fragmentation for TLS hello packet."
312316
"fragmentSett" = "Fragmentation Settings"

web/translation/translate.es_ES.toml

+4
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@
306306
"subShowInfo" = "Mostrar información de uso"
307307
"subShowInfoDesc" = "Mostrar tráfico restante y fecha después del nombre de configuración."
308308
"subURI" = "URI de proxy inverso"
309+
"externalTrafficInformEnable" = "Informe de tráfico externo"
310+
"externalTrafficInformEnableDesc" = "Informar a la API externa sobre cada actualización de tráfico."
311+
"externalTrafficInformURI" = "URI de información de tráfico externo"
312+
"externalTrafficInformURIDesc" = "Las actualizaciones de tráfico se envían a este URI."
309313
"subURIDesc" = "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy"
310314
"fragment" = "Fragmentación"
311315
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"

web/translation/translate.fa_IR.toml

+4
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@
301301
"subDomainDesc" = "آدرس دامنه برای سرویس سابسکریپشن. برای گوش دادن به تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید‌"
302302
"subUpdates" = "فاصله بروزرسانی‌ سابسکریپشن"
303303
"subUpdatesDesc" = "(فاصله مابین بروزرسانی در برنامه‌های کاربری. (واحد: ساعت"
304+
"externalTrafficInformEnable" = "اطلاع رسانی خارجی مصرف ترافیک"
305+
"externalTrafficInformEnableDesc" = "مصرف ترافیک به سرویس خارجی ارسال می شود"
306+
"externalTrafficInformURI" = "لینک اطلاع رسانی خارجی مصرف ترافیک"
307+
"externalTrafficInformURIDesc" = "ترافیک های مصرفی به این لینک هم ارسال می شود"
304308
"subEncrypt" = "کدگذاری"
305309
"subEncryptDesc" = "کدگذاری خواهدشد Base64 محتوای برگشتی سرویس سابسکریپشن برپایه"
306310
"subShowInfo" = "نمایش اطلاعات مصرف"

web/translation/translate.id_ID.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,10 @@
306306
"subShowInfo" = "Tampilkan Info Penggunaan"
307307
"subShowInfoDesc" = "Sisa traffic dan tanggal akan ditampilkan di aplikasi klien."
308308
"subURI" = "URI Proxy Terbalik"
309-
"subURIDesc" = "URI path URL langganan untuk penggunaan di belakang proxy."
309+
"externalTrafficInformEnable" = "Informasikan API eksternal pada setiap pembaruan lalu lintas."
310+
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
311+
"externalTrafficInformURI" = "Lalu Lintas Eksternal Menginformasikan URI"
312+
"externalTrafficInformURIDesc" = "Pembaruan lalu lintas dikirim ke URI ini."
310313
"fragment" = "Fragmentasi"
311314
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
312315
"fragmentSett" = "Pengaturan Fragmentasi"

web/translation/translate.ja_JP.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "クライアントアプリで残りのトラフィックと日付情報を表示する"
308308
"subURI" = "リバースプロキシURI"
309309
"subURIDesc" = "プロキシ後ろのサブスクリプションURLのURIパスに使用する"
310+
"externalTrafficInformEnable" = "外部トラフィック情報"
311+
"externalTrafficInformEnableDesc" = "トラフィックの更新ごとに外部 API に通知します。"
312+
"externalTrafficInformURI" = "外部トラフィック通知 URI"
313+
"externalTrafficInformURIDesc" = "トラフィックの更新ごとに外部 API に通知します。"
310314
"fragment" = "フラグメント"
311315
"fragmentDesc" = "TLS helloパケットのフラグメントを有効にする"
312316
"fragmentSett" = "設定"

web/translation/translate.pt_BR.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "O tráfego restante e a data serão exibidos nos aplicativos de cliente."
308308
"subURI" = "URI de Proxy Reverso"
309309
"subURIDesc" = "O caminho URI da URL de assinatura para uso por trás de proxies."
310+
"externalTrafficInformEnable" = "Informações de tráfego externo"
311+
"externalTrafficInformEnableDesc" = "Informar a API externa sobre cada atualização de tráfego."
312+
"externalTrafficInformURI" = "URI de informação de tráfego externo"
313+
"externalTrafficInformURIDesc" = "As atualizações de tráfego são enviadas para este URI."
310314
"fragment" = "Fragmentação"
311315
"fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello."
312316
"fragmentSett" = "Configurações de Fragmentação"

web/translation/translate.ru_RU.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "Показывать оставшиеся трафик и дату после имени конфигурации"
308308
"subURI" = "URI обратного прокси"
309309
"subURIDesc" = "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами"
310+
"externalTrafficInformEnable" = "Информация о внешнем трафике"
311+
"externalTrafficInformEnableDesc" = "Информировать внешний API о каждом обновлении трафика"
312+
"externalTrafficInformURI" = "URI информации о внешнем трафике"
313+
"externalTrafficInformURIDesc" = "Обновления трафика отправляются на этот URI"
310314
"fragment" = "Фрагментация"
311315
"fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS"
312316
"fragmentSett" = "Настройки фрагментации"

web/translation/translate.tr_TR.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "Kalan trafik ve tarih müşteri uygulamalarında görüntülenir."
308308
"subURI" = "Ters Proxy URI"
309309
"subURIDesc" = "Proxy arkasında kullanılacak abonelik URL'sinin URI yolu."
310+
"externalTrafficInformEnable" = "Harici Trafik Bilgisi"
311+
"externalTrafficInformEnableDesc" = "Her trafik güncellemesinde harici API'yi bilgilendirin."
312+
"externalTrafficInformURI" = "Harici Trafik Bilgisi URI'si"
313+
"externalTrafficInformURIDesc" = "Trafik güncellemeleri bu URI'ye gönderildi."
310314
"fragment" = "Parçalama"
311315
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
312316
"fragmentSett" = "Parçalama Ayarları"

web/translation/translate.uk_UA.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "Залишок трафіку та дата відображатимуться в клієнтських програмах."
308308
"subURI" = "URI зворотного проксі"
309309
"subURIDesc" = "URI до URL-адреси підписки для використання за проксі."
310+
"externalTrafficInformEnable" = "Інформація про зовнішній трафік"
311+
"externalTrafficInformEnableDesc" = "Інформувати зовнішній API про кожне оновлення трафіку."
312+
"externalTrafficInformURI" = "Інформаційний URI зовнішнього трафіку"
313+
"externalTrafficInformURIDesc" = "Оновлення трафіку надсилаються на цей URI."
310314
"fragment" = "Фрагментація"
311315
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
312316
"fragmentSett" = "Параметри фрагментації"

web/translation/translate.vi_VN.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình"
308308
"subURI" = "URI proxy trung gian"
309309
"subURIDesc" = "Thay đổi URI cơ sở của URL gói đăng ký để sử dụng cho proxy trung gian"
310+
"externalTrafficInformEnable" = "Thông báo giao thông bên ngoài"
311+
"externalTrafficInformEnableDesc" = "Thông báo cho API bên ngoài về mọi cập nhật lưu lượng truy cập."
312+
"externalTrafficInformURI" = "URI thông báo lưu lượng truy cập bên ngoài"
313+
"externalTrafficInformURIDesc" = "Cập nhật lưu lượng truy cập được gửi tới URI này."
310314
"fragment" = "Sự phân mảnh"
311315
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
312316
"fragmentSett" = "Cài đặt phân mảnh"

web/translation/translate.zh_CN.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "客户端应用中将显示剩余流量和日期信息"
308308
"subURI" = "反向代理 URI"
309309
"subURIDesc" = "用于代理后面的订阅 URL 的 URI 路径"
310+
"externalTrafficInformEnable" = "外部交通通知"
311+
"externalTrafficInformEnableDesc" = "每次流量更新时通知外部 API"
312+
"externalTrafficInformURI" = "外部流量通知 URI"
313+
"externalTrafficInformURIDesc" = "流量更新将发送到此 URI"
310314
"fragment" = "分片"
311315
"fragmentDesc" = "启用 TLS hello 数据包分片"
312316
"fragmentSett" = "设置"

web/translation/translate.zh_TW.toml

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@
307307
"subShowInfoDesc" = "客戶端應用中將顯示剩餘流量和日期資訊"
308308
"subURI" = "反向代理 URI"
309309
"subURIDesc" = "用於代理後面的訂閱 URL 的 URI 路徑"
310+
"externalTrafficInformEnable" = "外部交通通知"
311+
"externalTrafficInformEnableDesc" = "每次流量更新時通知外部 API"
312+
"externalTrafficInformURI" = "外部流量通知 URI"
313+
"externalTrafficInformURIDesc" = "流量更新將會傳送到此 URI"
310314
"fragment" = "分片"
311315
"fragmentDesc" = "啟用 TLS hello 資料包分片"
312316
"fragmentSett" = "設定"

0 commit comments

Comments
 (0)