ソースを参照

feat: custom subscription title in panel (#2773)

* feat: custom subscription title in panel

* feat: added translations
Ilya Afanasov 2 週間 前
コミット
d30cdbf49a

+ 6 - 1
sub/sub.go

@@ -107,11 +107,16 @@ func (s *Server) initRouter() (*gin.Engine, error) {
 		SubJsonRules = ""
 	}
 
+	SubTitle, err := s.settingService.GetSubTitle()
+	if err != nil {
+		SubTitle = ""
+	}
+
 	g := engine.Group("/")
 
 	s.sub = NewSUBController(
 		g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates,
-		SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules)
+		SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules, SubTitle)
 
 	return engine, nil
 }

+ 5 - 2
sub/subController.go

@@ -9,6 +9,7 @@ import (
 )
 
 type SUBController struct {
+	subTitle       string
 	subPath        string
 	subJsonPath    string
 	subEncrypt     bool
@@ -30,9 +31,11 @@ func NewSUBController(
 	jsonNoise string,
 	jsonMux string,
 	jsonRules string,
+	subTitle string,
 ) *SUBController {
 	sub := NewSubService(showInfo, rModel)
 	a := &SUBController{
+		subTitle:       subTitle,
 		subPath:        subPath,
 		subJsonPath:    jsonPath,
 		subEncrypt:     encrypt,
@@ -82,7 +85,7 @@ func (a *SUBController) subs(c *gin.Context) {
 		// Add headers
 		c.Writer.Header().Set("Subscription-Userinfo", header)
 		c.Writer.Header().Set("Profile-Update-Interval", a.updateInterval)
-		c.Writer.Header().Set("Profile-Title", subId)
+		c.Writer.Header().Set("Profile-Title", a.subTitle)
 
 		if a.subEncrypt {
 			c.String(200, base64.StdEncoding.EncodeToString([]byte(result)))
@@ -116,7 +119,7 @@ func (a *SUBController) subJsons(c *gin.Context) {
 		// Add headers
 		c.Writer.Header().Set("Subscription-Userinfo", header)
 		c.Writer.Header().Set("Profile-Update-Interval", a.updateInterval)
-		c.Writer.Header().Set("Profile-Title", subId)
+		c.Writer.Header().Set("Profile-Title", a.subTitle)
 
 		c.String(200, jsonSub)
 	}

+ 1 - 0
web/assets/js/model/setting.js

@@ -26,6 +26,7 @@ class AllSetting {
         this.xrayTemplateConfig = "";
         this.secretEnable = false;
         this.subEnable = false;
+        this.subTitle = "";
         this.subListen = "";
         this.subPort = 2096;
         this.subPath = "/sub/";

+ 1 - 0
web/entity/entity.go

@@ -40,6 +40,7 @@ type AllSetting struct {
 	TimeLocation                string `json:"timeLocation" form:"timeLocation"`
 	SecretEnable                bool   `json:"secretEnable" form:"secretEnable"`
 	SubEnable                   bool   `json:"subEnable" form:"subEnable"`
+	SubTitle                    string `json:"subTitle" form:"subTitle"`
 	SubListen                   string `json:"subListen" form:"subListen"`
 	SubPort                     int    `json:"subPort" form:"subPort"`
 	SubPath                     string `json:"subPath" form:"subPath"`

+ 2 - 0
web/html/xui/inbounds.html

@@ -662,6 +662,7 @@
             refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000,
             subSettings: {
                 enable : false,
+                subTitle : '',
                 subURI : '',
                 subJsonURI : '',
             },
@@ -711,6 +712,7 @@
                     this.tgBotEnable = tgBotEnable;
                     this.subSettings = {
                         enable : subEnable,
+                        subTitle : subTitle,
                         subURI: subURI,
                         subJsonURI: subJsonURI
                     };

+ 7 - 0
web/html/xui/settings.html

@@ -409,6 +409,13 @@
                         <a-switch v-model="allSetting.subEnable"></a-switch>
                       </template>
                     </a-setting-list-item>
+                    <a-setting-list-item paddings="small">
+                      <template #title>{{ i18n "pages.settings.subTitle"}}</template>
+                      <template #description>{{ i18n "pages.settings.subTitleDesc"}}</template>
+                      <template #control>
+                        <a-input type="text" v-model="allSetting.subTitle"></a-input>
+                      </template>
+                    </a-setting-list-item>
                     <a-setting-list-item paddings="small">
                       <template #title>{{ i18n "pages.settings.subListen"}}</template>
                       <template #description>{{ i18n "pages.settings.subListenDesc"}}</template>

+ 10 - 0
web/service/setting.go

@@ -50,6 +50,7 @@ var defaultValueMap = map[string]string{
 	"tgLang":                      "en-US",
 	"secretEnable":                "false",
 	"subEnable":                   "false",
+	"subTitle":                    "",
 	"subListen":                   "",
 	"subPort":                     "2096",
 	"subPath":                     "/sub/",
@@ -418,6 +419,10 @@ func (s *SettingService) GetSubEnable() (bool, error) {
 	return s.getBool("subEnable")
 }
 
+func (s *SettingService) GetSubTitle() (string, error) {
+	return s.getString("subTitle")
+}
+
 func (s *SettingService) GetSubListen() (string, error) {
 	return s.getString("subListen")
 }
@@ -562,6 +567,7 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
 		"defaultKey":    func() (any, error) { return s.GetKeyFile() },
 		"tgBotEnable":   func() (any, error) { return s.GetTgbotEnabled() },
 		"subEnable":     func() (any, error) { return s.GetSubEnable() },
+		"subTitle":      func() (any, error) { return s.GetSubTitle() },
 		"subURI":        func() (any, error) { return s.GetSubURI() },
 		"subJsonURI":    func() (any, error) { return s.GetSubJsonURI() },
 		"remarkModel":   func() (any, error) { return s.GetRemarkModel() },
@@ -581,6 +587,7 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
 
 	if result["subEnable"].(bool) && (result["subURI"].(string) == "" || result["subJsonURI"].(string) == "") {
 		subURI := ""
+		subTitle, _ := s.GetSubTitle()
 		subPort, _ := s.GetSubPort()
 		subPath, _ := s.GetSubPath()
 		subJsonPath, _ := s.GetSubJsonPath()
@@ -607,6 +614,9 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
 		if result["subURI"].(string) == "" {
 			result["subURI"] = subURI + subPath
 		}
+		if result["subTitle"].(string) == "" {
+			result["subTitle"] = subTitle
+		}
 		if result["subJsonURI"].(string) == "" {
 			result["subJsonURI"] = subURI + subJsonPath
 		}

+ 2 - 0
web/translation/translate.en_US.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Subscription"
 "subEnable" = "Enable Subscription Service"
 "subEnableDesc" = "Enables the subscription service."
+"subTitle" = "Subscription Title"
+ "subTitleDesc" = "Title shown in VPN client"
 "subListen" = "Listen IP"
 "subListenDesc" = "The IP address for the subscription service. (leave blank to listen on all IPs)"
 "subPort" = "Listen Port"

+ 2 - 0
web/translation/translate.es_ES.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Suscripción"
 "subEnable" = "Habilitar Servicio"
 "subEnableDesc" = "Función de suscripción con configuración separada."
+"subTitle" = "Título de la Suscripción"
+"subTitleDesc" = "Título mostrado en el cliente de VPN"
 "subListen" = "Listening IP"
 "subListenDesc" = "Dejar en blanco por defecto para monitorear todas las IPs."
 "subPort" = "Puerto de Suscripción"

+ 2 - 0
web/translation/translate.fa_IR.toml

@@ -292,6 +292,8 @@
 "subSettings" = "سابسکریپشن"
 "subEnable" = "فعال‌سازی سرویس سابسکریپشن"
 "subEnableDesc" = "سرویس سابسکریپشن‌ را فعال‌می‌کند"
+"subTitle" = "عنوان اشتراک"
+"subTitleDesc" = "عنوان نمایش داده شده در کلاینت VPN"
 "subListen" = "آدرس آی‌پی"
 "subListenDesc" = "آدرس آی‌پی برای سرویس سابسکریپشن. برای گوش دادن به‌تمام آی‌پی‌ها خالی‌بگذارید"
 "subPort" = "پورت"

+ 2 - 0
web/translation/translate.id_ID.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Langganan"
 "subEnable" = "Aktifkan Layanan Langganan"
 "subEnableDesc" = "Mengaktifkan layanan langganan."
+"subTitle" = "Judul Langganan"
+"subTitleDesc" = "Judul yang ditampilkan di klien VPN"
 "subListen" = "IP Pendengar"
 "subListenDesc" = "Alamat IP untuk layanan langganan. (biarkan kosong untuk mendengarkan semua IP)"
 "subPort" = "Port Pendengar"

+ 2 - 0
web/translation/translate.ja_JP.toml

@@ -292,6 +292,8 @@
 "subSettings" = "サブスクリプション設定"
 "subEnable" = "サブスクリプションサービスを有効にする"
 "subEnableDesc" = "サブスクリプションサービス機能を有効にする"
+"subTitle" = "サブスクリプションタイトル"
+"subTitleDesc" = "VPNクライアントに表示されるタイトル"
 "subListen" = "監視IP"
 "subListenDesc" = "サブスクリプションサービスが監視するIPアドレス(空白にするとすべてのIPを監視)"
 "subPort" = "監視ポート"

+ 2 - 0
web/translation/translate.pt_BR.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Assinatura"
 "subEnable" = "Ativar Serviço de Assinatura"
 "subEnableDesc" = "Ativa o serviço de assinatura."
+"subTitle" = "Título da Assinatura"
+"subTitleDesc" = "Título exibido no cliente VPN"
 "subListen" = "IP de Escuta"
 "subListenDesc" = "O endereço IP para o serviço de assinatura. (deixe em branco para escutar em todos os IPs)"
 "subPort" = "Porta de Escuta"

+ 2 - 0
web/translation/translate.ru_RU.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Подписка"
 "subEnable" = "Включить службу"
 "subEnableDesc" = "Функция подписки с отдельной конфигурацией"
+"subTitle" = "Заголовок подписки"
+ "subTitleDesc" = "Название подписки, которое видит клиент в VPN клиенте"
 "subListen" = "Прослушивание IP"
 "subListenDesc" = "Оставьте пустым по умолчанию, чтобы отслеживать все IP-адреса"
 "subPort" = "Порт подписки"

+ 2 - 0
web/translation/translate.tr_TR.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Abonelik"
 "subEnable" = "Abonelik Hizmetini Etkinleştir"
 "subEnableDesc" = "Abonelik hizmetini etkinleştirir."
+"subTitle" = "Abonelik Başlığı"
+"subTitleDesc" = "VPN istemcisinde gösterilen başlık"
 "subListen" = "Dinleme IP"
 "subListenDesc" = "Abonelik hizmeti için IP adresi. (tüm IP'leri dinlemek için boş bırakın)"
 "subPort" = "Dinleme Portu"

+ 2 - 0
web/translation/translate.uk_UA.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Підписка"
 "subEnable" = "Увімкнути службу підписки"
 "subEnableDesc" = "Вмикає службу підписки."
+"subTitle" = "Назва Підписки"
+"subTitleDesc" = "Назва, яка відображається у VPN-клієнті"
 "subListen" = "Слухати IP"
 "subListenDesc" = "IP-адреса для служби підписки. (залиште порожнім, щоб слухати всі IP-адреси)"
 "subPort" = "Слухати порт"

+ 2 - 0
web/translation/translate.vi_VN.toml

@@ -292,6 +292,8 @@
 "subSettings" = "Gói đăng ký"
 "subEnable" = "Bật dịch vụ"
 "subEnableDesc" = "Tính năng gói đăng ký với cấu hình riêng"
+"subTitle" = "Tiêu đề Đăng ký"
+"subTitleDesc" = "Tiêu đề hiển thị trong ứng dụng VPN"
 "subListen" = "Listening IP"
 "subListenDesc" = "Mặc định để trống để nghe tất cả các IP"
 "subPort" = "Cổng gói đăng ký"

+ 2 - 0
web/translation/translate.zh_CN.toml

@@ -292,6 +292,8 @@
 "subSettings" = "订阅设置"
 "subEnable" = "启用订阅服务"
 "subEnableDesc" = "启用订阅服务功能"
+"subTitle" = "订阅标题"
+"subTitleDesc" = "在VPN客户端中显示的标题"
 "subListen" = "监听 IP"
 "subListenDesc" = "订阅服务监听的 IP 地址(留空表示监听所有 IP)"
 "subPort" = "监听端口"

+ 2 - 0
web/translation/translate.zh_TW.toml

@@ -292,6 +292,8 @@
 "subSettings" = "訂閱設定"
 "subEnable" = "啟用訂閱服務"
 "subEnableDesc" = "啟用訂閱服務功能"
+"subTitle" = "訂閱標題"
+"subTitleDesc" = "在VPN客戶端中顯示的標題"
 "subListen" = "監聽 IP"
 "subListenDesc" = "訂閱服務監聽的 IP 地址(留空表示監聽所有 IP)"
 "subPort" = "監聽埠"