Browse Source

import-export inbound #1300

Alireza Ahmadi 1 year ago
parent
commit
35feef650f

+ 27 - 0
web/controller/inbound.go

@@ -1,6 +1,7 @@
 package controller
 
 import (
+	"encoding/json"
 	"fmt"
 	"strconv"
 	"x-ui/database/model"
@@ -37,6 +38,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
 	g.POST("/resetAllTraffics", a.resetAllTraffics)
 	g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics)
 	g.POST("/delDepletedClients/:id", a.delDepletedClients)
+	g.POST("/import", a.importInbound)
 	g.POST("/onlines", a.onlines)
 }
 
@@ -266,6 +268,31 @@ func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
 	jsonMsg(c, "All traffics of client reseted", nil)
 }
 
+func (a *InboundController) importInbound(c *gin.Context) {
+	inbound := &model.Inbound{}
+	err := json.Unmarshal([]byte(c.PostForm("data")), inbound)
+	if err != nil {
+		jsonMsg(c, "Something went wrong!", err)
+		return
+	}
+	user := session.GetLoginUser(c)
+	inbound.Id = 0
+	inbound.UserId = user.Id
+	inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
+
+	for index := range inbound.ClientStats {
+		inbound.ClientStats[index].Id = 0
+		inbound.ClientStats[index].Enable = true
+	}
+
+	needRestart := false
+	inbound, needRestart, err = a.inboundService.AddInbound(inbound)
+	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.create"), inbound, err)
+	if err == nil && needRestart {
+		a.xrayService.SetToNeedRestart()
+	}
+}
+
 func (a *InboundController) delDepletedClients(c *gin.Context) {
 	id, err := strconv.Atoi(c.Param("id"))
 	if err != nil {

+ 0 - 1
web/html/common/prompt_modal.html

@@ -1,7 +1,6 @@
 {{define "promptModal"}}
 <a-modal id="prompt-modal" v-model="promptModal.visible" :title="promptModal.title"
          :closable="true" @ok="promptModal.ok" :mask-closable="false"
-         :class="themeSwitcher.darkCardClass"
          :ok-text="promptModal.okText" cancel-text='{{ i18n "cancel" }}' :class="themeSwitcher.currentTheme">
     <a-input id="prompt-modal-input" :type="promptModal.type"
              v-model="promptModal.value"

+ 4 - 1
web/html/common/text_modal.html

@@ -31,7 +31,10 @@
                     this.clipboard = new ClipboardJS('#txt-modal-ok-btn', {
                         text: () => this.content,
                     });
-                    this.clipboard.on('success', () => app.$message.success('{{ i18n "copied" }}'));
+                    this.clipboard.on('success', () => {
+                        app.$message.success('{{ i18n "copied" }}')
+                        this.close();
+                    });
                 }
             });
         },

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

@@ -121,6 +121,10 @@
                                             <template v-if="!isMobile">{{ i18n "pages.inbounds.generalActions" }}</template>
                                         </a-button>
                                         <a-menu slot="overlay" @click="a => generalActions(a)" :theme="themeSwitcher.currentTheme">
+                                            <a-menu-item key="import">
+                                                <a-icon type="import"></a-icon>
+                                                {{ i18n "pages.inbounds.importInbound" }}
+                                            </a-menu-item>
                                             <a-menu-item key="export">
                                                 <a-icon type="export"></a-icon>
                                                 {{ i18n "pages.inbounds.export" }}
@@ -221,6 +225,10 @@
                                                 {{ i18n "info"}}
                                             </a-menu-item>
                                         </template>
+                                        <a-menu-item key="clipboard">
+                                            <a-icon type="copy"></a-icon>
+                                            {{ i18n "pages.inbounds.copyToClipboard" }}
+                                        </a-menu-item>
                                         <a-menu-item key="resetTraffic">
                                             <a-icon type="retweet"></a-icon> {{ i18n "pages.inbounds.resetTraffic" }}
                                         </a-menu-item>
@@ -708,6 +716,9 @@
             },
             generalActions(action) {
                 switch (action.key) {
+                    case "import":
+                        this.importInbound();
+                        break;
                     case "export":
                         this.exportAllLinks();
                         break;
@@ -742,6 +753,9 @@
                     case "export":
                         this.inboundLinks(dbInbound.id);
                         break;
+                    case "clipboard":
+                        this.copyToClipboard(dbInbound.id);
+                        break;
                     case "resetTraffic":
                         this.resetTraffic(dbInbound.id);
                         break;
@@ -1162,6 +1176,18 @@
                 newDbInbound = this.checkFallback(dbInbound);
                 txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks, newDbInbound.remark);
             },
+            importInbound() {
+                promptModal.open({
+                    title: '{{ i18n "pages.inbounds.importInbound" }}',
+                    type: 'textarea',
+                    value: '',
+                    okText: '{{ i18n "pages.inbounds.import" }}',
+                    confirm: async (dbInboundText) => {
+                        await this.submit('/panel/inbound/import', {data: dbInboundText}, promptModal);
+                        promptModal.close();
+                    },
+                });
+            },
             exportAllLinks() {
                 let copyText = [];
                 for (const dbInbound of this.dbInbounds) {
@@ -1169,6 +1195,10 @@
                 }
                 txtModal.show('{{ i18n "pages.inbounds.export"}}', copyText.join('\r\n'), 'All-Inbounds');
             },
+            copyToClipboard(dbInboundId) {
+                dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+                txtModal.show('{{ i18n "pages.inbounds.inboundData" }}', JSON.stringify(dbInbound, null, 2));
+            },
             async startDataRefreshLoop() {
                 while (this.isRefreshEnabled) {
                     try {

+ 6 - 2
web/service/inbound.go

@@ -168,9 +168,13 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, boo
 
 	err = tx.Save(inbound).Error
 	if err == nil {
-		for _, client := range clients {
-			s.AddClientStat(tx, inbound.Id, &client)
+		if len(inbound.ClientStats) == 0 {
+			for _, client := range clients {
+				s.AddClientStat(tx, inbound.Id, &client)
+			}
 		}
+	} else {
+		return inbound, false, err
 	}
 
 	needRestart := false

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

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "you can find your sub link on Details, also you can use the same name for several configurations"
 "info" = "Info"
 "same" = "Same"
+"inboundData" = "Inbound's data"
+"copyToClipboard" = "Copy to clipboard"
+"import" = "Import"
+"importInbound" = "Import an inbound"
 
 [pages.client]
 "add" = "Add Client"

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

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones."
 "info" = "Info"
 "same" = "misma"
+"inboundData" = "Datos de entrada"
+"copyToClipboard" = "Copiar al portapapeles"
+"import" = "Importar"
+"importInbound" = "Importar un entrante"
 
 [pages.client]
 "add" = "Agregar Cliente"

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

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "می توانید ساب لینک خود را در جزئیات پیدا کنید، همچنین می توانید از همین نام برای چندین کانفیگ استفاده کنید"
 "info" = "اطلاعات"
 "same" = "همسان"
+"inboundData" = "داده‌های سرویس"
+"copyToClipboard" = "کپی در حافظه"
+"import" = "وارد کردن"
+"importInbound" = "وارد کردن یک سرویس"
 
 [pages.client]
 "add" = "کاربر جدید"

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

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций"
 "info" = "Информация"
 "same" = "Тот же"
+"inboundData" = "Входящие данные"
+"copyToClipboard" = "Копировать в буфер обмена"
+"import" = "Импортировать"
+"importInbound" = "Импортировать входящее сообщение"
 
 [pages.client]
 "add" = "Добавить пользователя"

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

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "Bạn có thể tìm liên kết đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau"
 "info" = "Thông tin"
 "same" = "Giống nhau"
+"inboundData" = "Dữ liệu gửi đến"
+"copyToClipboard" = "Sao chép vào bảng nhớ tạm"
+"import" = "Nhập"
+"importInbound" = "Nhập hàng gửi về"
 
 [pages.client]
 "add" = "Thêm Client"

+ 4 - 0
web/translation/translate.zh_Hans.toml

@@ -177,6 +177,10 @@
 "subscriptionDesc" = "您可以在详细信息上找到您的子链接,也可以对多个配置使用相同的名称"
 "info" = "信息"
 "same" = "相同"
+"inboundData" = "入站数据"
+"copyToClipboard" = "复制到剪贴板"
+"import"="导入"
+"importInbound" = "导入入站"
 
 [pages.client]
 "add" = "添加客户端"