From fd64ae5c855201fb0078a3ed549a0e1069b062b2 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Thu, 7 Dec 2023 12:58:19 +0100 Subject: [PATCH] [feature] import-export inbound #699 --- web/controller/inbound.go | 27 ++++++++++++++++++++++ web/html/common/text_modal.html | 5 +++- web/html/xui/inbounds.html | 32 +++++++++++++++++++++++++- web/service/inbound.go | 8 +++++-- web/translation/translate.en_US.toml | 4 ++++ web/translation/translate.fa_IR.toml | 6 ++++- web/translation/translate.ru_RU.toml | 4 ++++ web/translation/translate.vi_VN.toml | 4 ++++ web/translation/translate.zh_Hans.toml | 4 ++++ 9 files changed, 89 insertions(+), 5 deletions(-) diff --git a/web/controller/inbound.go b/web/controller/inbound.go index 6350ece8..02573bd7 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -1,6 +1,7 @@ package controller import ( + "encoding/json" "fmt" "strconv" "x-ui/database/model" @@ -35,6 +36,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) } @@ -254,6 +256,31 @@ func (a *InboundController) delDepletedClients(c *gin.Context) { jsonMsg(c, "All delpeted clients are deleted", 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) onlines(c *gin.Context) { jsonObj(c, a.inboundService.GetOnlineClinets(), nil) } diff --git a/web/html/common/text_modal.html b/web/html/common/text_modal.html index 453875ca..26ac5ade 100644 --- a/web/html/common/text_modal.html +++ b/web/html/common/text_modal.html @@ -30,7 +30,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(); + }); } }); }, diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 94bf52d9..114eef67 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -125,6 +125,10 @@ + + + {{ i18n "pages.inbounds.importInbound" }} + {{ i18n "pages.inbounds.export" }} @@ -226,6 +230,10 @@ {{ i18n "pages.inbounds.resetTraffic" }} + + + {{ i18n "pages.inbounds.copyToClipboard" }} + {{ i18n "pages.inbounds.clone"}} @@ -707,6 +715,9 @@ }, generalActions(action) { switch (action.key) { + case "import": + this.importInbound(); + break; case "export": this.exportAllLinks(); break; @@ -741,6 +752,9 @@ case "export": this.inboundLinks(dbInbound.id); break; + case "clipboard": + this.copyToClipboard(dbInbound.id); + break; case "resetTraffic": this.resetTraffic(dbInbound.id); break; @@ -792,7 +806,7 @@ this.$confirm({ title: '{{ i18n "pages.inbounds.cloneInbound"}} \"' + dbInbound.remark + '\"', content: '{{ i18n "pages.inbounds.cloneInboundContent"}}', - okText: '{{ i18n "pages.inbounds.update"}}', + okText: '{{ i18n "pages.inbounds.clone"}}', class: themeSwitcher.currentTheme, cancelText: '{{ i18n "cancel" }}', onOk: () => { @@ -1160,6 +1174,18 @@ dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); 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('/xui/inbound/import', {data: dbInboundText}, promptModal); + promptModal.close(); + }, + }); }, exportAllLinks() { let copyText = []; @@ -1168,6 +1194,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 { diff --git a/web/service/inbound.go b/web/service/inbound.go index 35cd0911..c2a26185 100644 --- a/web/service/inbound.go +++ b/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 diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 68c5c55d..a6ce5e28 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -170,6 +170,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" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 56214c7f..700a8ad0 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -148,7 +148,7 @@ "client" = "کاربر" "export" = "استخراج لینک‌ها" "clone" = "شبیه سازی" -"cloneInbound" = "ایجاد" +"cloneInbound" = "شبیه‌سازی سرویس" "cloneInboundContent" = "همه موارد این ورودی بجز پورت ، ای پی و کلاینت ها شبیه سازی خواهند شد" "resetAllTraffic" = "ریست ترافیک کل سرویس ها" "resetAllTrafficTitle" = "ریست ترافیک کل سرویس ها" @@ -169,6 +169,10 @@ "subscriptionDesc" = "می توانید ساب لینک خود را در جزئیات پیدا کنید، همچنین می توانید از همین نام برای چندین کانفیگ استفاده کنید" "info" = "اطلاعات" "same" = "همسان" +"inboundData" = "داده‌های سرویس" +"copyToClipboard" = "کپی در حافظه" +"import" = "وارد کردن" +"importInbound" = "وارد کردن یک سرویس" [pages.client] "add" = "کاربر جدید" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 4d509b08..26d8ef42 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -170,6 +170,10 @@ "subscriptionDesc" = "вы можете найти свою ссылку подписки в разделе «Подробнее», также вы можете использовать одно и то же имя для нескольких конфигов" "info" = "Информация" "same" = "Тот же" +"inboundData" = "Входящие данные" +"copyToClipboard" = "Копировать в буфер обмена" +"import" = "Импортировать" +"importInbound" = "Импортировать входящее сообщение" [pages.client] "add" = "Добавить клиента" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index d6004311..59616df6 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -170,6 +170,10 @@ "subscriptionDesc" = "Bạn có thể tìm thấy liên kết phụ của mình trên Chi tiết, bạn cũng có thể sử dụng cùng tên cho một số cấu hình" "info" = "Thông tin" "same" = "Như 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 máy khách" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index 6548be50..4a948e5d 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -170,6 +170,10 @@ "subscriptionDesc" = "您可以在详细信息上找到您的子链接,也可以对多个配置使用相同的名称" "info" = "信息" "same" = "相同" +"inboundData" = "入站数据" +"copyToClipboard" = "复制到剪贴板" +"import"="导入" +"importInbound" = "导入入站" [pages.client] "add" = "添加客户端"