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.generalActions" }}
generalActions(a)" :theme="themeSwitcher.currentTheme">
+
+
+ {{ 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" = "添加客户端"