mirror of
				https://github.com/MHSanaei/3x-ui.git
				synced 2025-10-31 04:12:51 +00:00 
			
		
		
		
	api (#3434)
	
		
			
	
		
	
	
		
	
		
			Some checks are pending
		
		
	
	
		
			
				
	
				Release 3X-UI / build (386) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (amd64) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (arm64) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (armv5) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (armv6) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (armv7) (push) Waiting to run
				
			
		
			
				
	
				Release 3X-UI / build (s390x) (push) Waiting to run
				
			
		
		
	
	
				
					
				
			
		
			Some checks are pending
		
		
	
	Release 3X-UI / build (386) (push) Waiting to run
				
			Release 3X-UI / build (amd64) (push) Waiting to run
				
			Release 3X-UI / build (arm64) (push) Waiting to run
				
			Release 3X-UI / build (armv5) (push) Waiting to run
				
			Release 3X-UI / build (armv6) (push) Waiting to run
				
			Release 3X-UI / build (armv7) (push) Waiting to run
				
			Release 3X-UI / build (s390x) (push) Waiting to run
				
			This commit is contained in:
		
							parent
							
								
									18d74d54ca
								
							
						
					
					
						commit
						fe9f0d1d0e
					
				
					 14 changed files with 141 additions and 106 deletions
				
			
		|  | @ -9,6 +9,7 @@ import ( | ||||||
| type APIController struct { | type APIController struct { | ||||||
| 	BaseController | 	BaseController | ||||||
| 	inboundController *InboundController | 	inboundController *InboundController | ||||||
|  | 	serverController  *ServerController | ||||||
| 	Tgbot             service.Tgbot | 	Tgbot             service.Tgbot | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -19,43 +20,22 @@ func NewAPIController(g *gin.RouterGroup) *APIController { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *APIController) initRouter(g *gin.RouterGroup) { | func (a *APIController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g = g.Group("/panel/api/inbounds") | 	// Main API group
 | ||||||
| 	g.Use(a.checkLogin) | 	api := g.Group("/panel/api") | ||||||
|  | 	api.Use(a.checkLogin) | ||||||
| 
 | 
 | ||||||
| 	a.inboundController = NewInboundController(g) | 	// Inbounds API
 | ||||||
|  | 	inbounds := api.Group("/inbounds") | ||||||
|  | 	a.inboundController = NewInboundController(inbounds) | ||||||
| 
 | 
 | ||||||
| 	inboundRoutes := []struct { | 	// Server API
 | ||||||
| 		Method  string | 	server := api.Group("/server") | ||||||
| 		Path    string | 	a.serverController = NewServerController(server) | ||||||
| 		Handler gin.HandlerFunc |  | ||||||
| 	}{ |  | ||||||
| 		{"GET", "/createbackup", a.createBackup}, |  | ||||||
| 		{"GET", "/list", a.inboundController.getInbounds}, |  | ||||||
| 		{"GET", "/get/:id", a.inboundController.getInbound}, |  | ||||||
| 		{"GET", "/getClientTraffics/:email", a.inboundController.getClientTraffics}, |  | ||||||
| 		{"GET", "/getClientTrafficsById/:id", a.inboundController.getClientTrafficsById}, |  | ||||||
| 		{"POST", "/add", a.inboundController.addInbound}, |  | ||||||
| 		{"POST", "/del/:id", a.inboundController.delInbound}, |  | ||||||
| 		{"POST", "/update/:id", a.inboundController.updateInbound}, |  | ||||||
| 		{"POST", "/clientIps/:email", a.inboundController.getClientIps}, |  | ||||||
| 		{"POST", "/clearClientIps/:email", a.inboundController.clearClientIps}, |  | ||||||
| 		{"POST", "/addClient", a.inboundController.addInboundClient}, |  | ||||||
| 		{"POST", "/:id/delClient/:clientId", a.inboundController.delInboundClient}, |  | ||||||
| 		{"POST", "/updateClient/:clientId", a.inboundController.updateInboundClient}, |  | ||||||
| 		{"POST", "/:id/resetClientTraffic/:email", a.inboundController.resetClientTraffic}, |  | ||||||
| 		{"POST", "/resetAllTraffics", a.inboundController.resetAllTraffics}, |  | ||||||
| 		{"POST", "/resetAllClientTraffics/:id", a.inboundController.resetAllClientTraffics}, |  | ||||||
| 		{"POST", "/delDepletedClients/:id", a.inboundController.delDepletedClients}, |  | ||||||
| 		{"POST", "/onlines", a.inboundController.onlines}, |  | ||||||
| 		{"POST", "/lastOnline", a.inboundController.lastOnline}, |  | ||||||
| 		{"POST", "/updateClientTraffic/:email", a.inboundController.updateClientTraffic}, |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	for _, route := range inboundRoutes { | 	// Extra routes
 | ||||||
| 		g.Handle(route.Method, route.Path, route.Handler) | 	api.GET("/backuptotgbot", a.BackuptoTgbot) | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *APIController) createBackup(c *gin.Context) { | func (a *APIController) BackuptoTgbot(c *gin.Context) { | ||||||
| 	a.Tgbot.SendBackupToAdmins() | 	a.Tgbot.SendBackupToAdmins() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,9 +24,12 @@ func NewInboundController(g *gin.RouterGroup) *InboundController { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *InboundController) initRouter(g *gin.RouterGroup) { | func (a *InboundController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g = g.Group("/inbound") |  | ||||||
| 
 | 
 | ||||||
| 	g.POST("/list", a.getInbounds) | 	g.GET("/list", a.getInbounds) | ||||||
|  | 	g.GET("/get/:id", a.getInbound) | ||||||
|  | 	g.GET("/getClientTraffics/:email", a.getClientTraffics) | ||||||
|  | 	g.GET("/getClientTrafficsById/:id", a.getClientTrafficsById) | ||||||
|  | 
 | ||||||
| 	g.POST("/add", a.addInbound) | 	g.POST("/add", a.addInbound) | ||||||
| 	g.POST("/del/:id", a.delInbound) | 	g.POST("/del/:id", a.delInbound) | ||||||
| 	g.POST("/update/:id", a.updateInbound) | 	g.POST("/update/:id", a.updateInbound) | ||||||
|  | @ -41,6 +44,8 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g.POST("/delDepletedClients/:id", a.delDepletedClients) | 	g.POST("/delDepletedClients/:id", a.delDepletedClients) | ||||||
| 	g.POST("/import", a.importInbound) | 	g.POST("/import", a.importInbound) | ||||||
| 	g.POST("/onlines", a.onlines) | 	g.POST("/onlines", a.onlines) | ||||||
|  | 	g.POST("/lastOnline", a.lastOnline) | ||||||
|  | 	g.POST("/updateClientTraffic/:email", a.updateClientTraffic) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *InboundController) getInbounds(c *gin.Context) { | func (a *InboundController) getInbounds(c *gin.Context) { | ||||||
|  |  | ||||||
|  | @ -37,11 +37,17 @@ func NewServerController(g *gin.RouterGroup) *ServerController { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *ServerController) initRouter(g *gin.RouterGroup) { | func (a *ServerController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g = g.Group("/server") |  | ||||||
| 
 | 
 | ||||||
| 	g.Use(a.checkLogin) | 	g.GET("/status", a.status) | ||||||
| 	g.POST("/status", a.status) | 	g.GET("/getXrayVersion", a.getXrayVersion) | ||||||
| 	g.POST("/getXrayVersion", a.getXrayVersion) | 	g.GET("/getConfigJson", a.getConfigJson) | ||||||
|  | 	g.GET("/getDb", a.getDb) | ||||||
|  | 	g.GET("/getNewUUID", a.getNewUUID) | ||||||
|  | 	g.GET("/getNewX25519Cert", a.getNewX25519Cert) | ||||||
|  | 	g.GET("/getNewmldsa65", a.getNewmldsa65) | ||||||
|  | 	g.GET("/getNewmlkem768", a.getNewmlkem768) | ||||||
|  | 	g.GET("/getNewVlessEnc", a.getNewVlessEnc) | ||||||
|  | 
 | ||||||
| 	g.POST("/stopXrayService", a.stopXrayService) | 	g.POST("/stopXrayService", a.stopXrayService) | ||||||
| 	g.POST("/restartXrayService", a.restartXrayService) | 	g.POST("/restartXrayService", a.restartXrayService) | ||||||
| 	g.POST("/installXray/:version", a.installXray) | 	g.POST("/installXray/:version", a.installXray) | ||||||
|  | @ -49,13 +55,8 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g.POST("/updateGeofile/:fileName", a.updateGeofile) | 	g.POST("/updateGeofile/:fileName", a.updateGeofile) | ||||||
| 	g.POST("/logs/:count", a.getLogs) | 	g.POST("/logs/:count", a.getLogs) | ||||||
| 	g.POST("/xraylogs/:count", a.getXrayLogs) | 	g.POST("/xraylogs/:count", a.getXrayLogs) | ||||||
| 	g.POST("/getConfigJson", a.getConfigJson) |  | ||||||
| 	g.GET("/getDb", a.getDb) |  | ||||||
| 	g.POST("/importDB", a.importDB) | 	g.POST("/importDB", a.importDB) | ||||||
| 	g.POST("/getNewX25519Cert", a.getNewX25519Cert) |  | ||||||
| 	g.POST("/getNewmldsa65", a.getNewmldsa65) |  | ||||||
| 	g.POST("/getNewEchCert", a.getNewEchCert) | 	g.POST("/getNewEchCert", a.getNewEchCert) | ||||||
| 	g.POST("/getNewVlessEnc", a.getNewVlessEnc) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a *ServerController) refreshStatus() { | func (a *ServerController) refreshStatus() { | ||||||
|  | @ -276,3 +277,22 @@ func (a *ServerController) getNewVlessEnc(c *gin.Context) { | ||||||
| 	} | 	} | ||||||
| 	jsonObj(c, out, nil) | 	jsonObj(c, out, nil) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (a *ServerController) getNewUUID(c *gin.Context) { | ||||||
|  | 	uuidResp, err := a.serverService.GetNewUUID() | ||||||
|  | 	if err != nil { | ||||||
|  | 		jsonMsg(c, "Failed to generate UUID", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	jsonObj(c, uuidResp, nil) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *ServerController) getNewmlkem768(c *gin.Context) { | ||||||
|  | 	out, err := a.serverService.GetNewmlkem768() | ||||||
|  | 	if err != nil { | ||||||
|  | 		jsonMsg(c, "Failed to generate mlkem768 keys", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	jsonObj(c, out, nil) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ type XUIController struct { | ||||||
| 	BaseController | 	BaseController | ||||||
| 
 | 
 | ||||||
| 	inboundController     *InboundController | 	inboundController     *InboundController | ||||||
|  | 	serverController      *ServerController | ||||||
| 	settingController     *SettingController | 	settingController     *SettingController | ||||||
| 	xraySettingController *XraySettingController | 	xraySettingController *XraySettingController | ||||||
| } | } | ||||||
|  | @ -28,6 +29,7 @@ func (a *XUIController) initRouter(g *gin.RouterGroup) { | ||||||
| 	g.GET("/xray", a.xraySettings) | 	g.GET("/xray", a.xraySettings) | ||||||
| 
 | 
 | ||||||
| 	a.inboundController = NewInboundController(g) | 	a.inboundController = NewInboundController(g) | ||||||
|  | 	a.serverController = NewServerController(g) | ||||||
| 	a.settingController = NewSettingController(g) | 	a.settingController = NewSettingController(g) | ||||||
| 	a.xraySettingController = NewXraySettingController(g) | 	a.xraySettingController = NewXraySettingController(g) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ | ||||||
|       <a-input v-model.trim="inbound.settings.decryption"></a-input> |       <a-input v-model.trim="inbound.settings.decryption"></a-input> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item label="encryption"> |     <a-form-item label="encryption"> | ||||||
|       <a-input v-model="inbound.settings.encryption" disabled></a-input> |       <a-input v-model="inbound.settings.encryption"></a-input> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item label=" "> |     <a-form-item label=" "> | ||||||
|       <a-space> |       <a-space> | ||||||
|  |  | ||||||
|  | @ -830,7 +830,7 @@ | ||||||
|             }, |             }, | ||||||
|             async getDBInbounds() { |             async getDBInbounds() { | ||||||
|                 this.refreshing = true; |                 this.refreshing = true; | ||||||
|                 const msg = await HttpUtil.post('/panel/inbound/list'); |                 const msg = await HttpUtil.get('/panel/api/inbounds/list'); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     this.refreshing = false; |                     this.refreshing = false; | ||||||
|                     return; |                     return; | ||||||
|  | @ -845,7 +845,7 @@ | ||||||
|                 }, 500); |                 }, 500); | ||||||
|             }, |             }, | ||||||
|             async getOnlineUsers() { |             async getOnlineUsers() { | ||||||
|                 const msg = await HttpUtil.post('/panel/inbound/onlines'); |                 const msg = await HttpUtil.post('/panel/api/inbounds/onlines'); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  | @ -1099,7 +1099,7 @@ | ||||||
|                     streamSettings: baseInbound.stream.toString(), |                     streamSettings: baseInbound.stream.toString(), | ||||||
|                     sniffing: baseInbound.sniffing.toString(), |                     sniffing: baseInbound.sniffing.toString(), | ||||||
|                 }; |                 }; | ||||||
|                 await this.submit('/panel/inbound/add', data, inModal); |                 await this.submit('/panel/api/inbounds/add', data, inModal); | ||||||
|             }, |             }, | ||||||
|             openAddInbound() { |             openAddInbound() { | ||||||
|                 inModal.show({ |                 inModal.show({ | ||||||
|  | @ -1148,7 +1148,7 @@ | ||||||
|                 } |                 } | ||||||
|                 data.sniffing = inbound.sniffing.toString(); |                 data.sniffing = inbound.sniffing.toString(); | ||||||
| 
 | 
 | ||||||
|                 await this.submit('/panel/inbound/add', data, inModal); |                 await this.submit('/panel/api/inbounds/add', data, inModal); | ||||||
|             }, |             }, | ||||||
|             async updateInbound(inbound, dbInbound) { |             async updateInbound(inbound, dbInbound) { | ||||||
|                 const data = { |                 const data = { | ||||||
|  | @ -1171,7 +1171,7 @@ | ||||||
|                 } |                 } | ||||||
|                 data.sniffing = inbound.sniffing.toString(); |                 data.sniffing = inbound.sniffing.toString(); | ||||||
| 
 | 
 | ||||||
|                 await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); |                 await this.submit(`/panel/api/inbounds/update/${dbInbound.id}`, data, inModal); | ||||||
|             }, |             }, | ||||||
|             openAddClient(dbInboundId) { |             openAddClient(dbInboundId) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|  | @ -1226,14 +1226,14 @@ | ||||||
|                     id: dbInboundId, |                     id: dbInboundId, | ||||||
|                     settings: '{"clients": [' + clients.toString() + ']}', |                     settings: '{"clients": [' + clients.toString() + ']}', | ||||||
|                 }; |                 }; | ||||||
|                 await this.submit(`/panel/inbound/addClient`, data, modal); |                 await this.submit(`/panel/api/inbounds/addClient`, data, modal); | ||||||
|             }, |             }, | ||||||
|             async updateClient(client, dbInboundId, clientId) { |             async updateClient(client, dbInboundId, clientId) { | ||||||
|                 const data = { |                 const data = { | ||||||
|                     id: dbInboundId, |                     id: dbInboundId, | ||||||
|                     settings: '{"clients": [' + client.toString() + ']}', |                     settings: '{"clients": [' + client.toString() + ']}', | ||||||
|                 }; |                 }; | ||||||
|                 await this.submit(`/panel/inbound/updateClient/${clientId}`, data, clientModal); |                 await this.submit(`/panel/api/inbounds/updateClient/${clientId}`, data, clientModal); | ||||||
|             }, |             }, | ||||||
|             resetTraffic(dbInboundId) { |             resetTraffic(dbInboundId) { | ||||||
|                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |                 dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|  | @ -1258,7 +1258,7 @@ | ||||||
|                     class: themeSwitcher.currentTheme, |                     class: themeSwitcher.currentTheme, | ||||||
|                     okText: '{{ i18n "delete"}}', |                     okText: '{{ i18n "delete"}}', | ||||||
|                     cancelText: '{{ i18n "cancel"}}', |                     cancelText: '{{ i18n "cancel"}}', | ||||||
|                     onOk: () => this.submit('/panel/inbound/del/' + dbInboundId), |                     onOk: () => this.submit('/panel/api/inbounds/del/' + dbInboundId), | ||||||
|                 }); |                 }); | ||||||
|             }, |             }, | ||||||
|             delClient(dbInboundId, client,confirmation = true) { |             delClient(dbInboundId, client,confirmation = true) { | ||||||
|  | @ -1271,10 +1271,10 @@ | ||||||
|                         class: themeSwitcher.currentTheme, |                         class: themeSwitcher.currentTheme, | ||||||
|                         okText: '{{ i18n "delete"}}', |                         okText: '{{ i18n "delete"}}', | ||||||
|                         cancelText: '{{ i18n "cancel"}}', |                         cancelText: '{{ i18n "cancel"}}', | ||||||
|                         onOk: () => this.submit(`/panel/inbound/${dbInboundId}/delClient/${clientId}`), |                         onOk: () => this.submit(`/panel/api/inbounds/${dbInboundId}/delClient/${clientId}`), | ||||||
|                     }); |                     }); | ||||||
|                 } else { |                 } else { | ||||||
|                     this.submit(`/panel/inbound/${dbInboundId}/delClient/${clientId}`); |                     this.submit(`/panel/api/inbounds/${dbInboundId}/delClient/${clientId}`); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             getSubGroupClients(dbInbounds, currentClient) { |             getSubGroupClients(dbInbounds, currentClient) { | ||||||
|  | @ -1353,7 +1353,7 @@ | ||||||
|             switchEnable(dbInboundId,state) { |             switchEnable(dbInboundId,state) { | ||||||
|               dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); |               dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); | ||||||
|               dbInbound.enable = state; |               dbInbound.enable = state; | ||||||
|               this.submit(`/panel/inbound/update/${dbInboundId}`, dbInbound); |               this.submit(`/panel/api/inbounds/update/${dbInboundId}`, dbInbound); | ||||||
|             }, |             }, | ||||||
|             async switchEnableClient(dbInboundId, client) { |             async switchEnableClient(dbInboundId, client) { | ||||||
|                 this.loading() |                 this.loading() | ||||||
|  | @ -1383,10 +1383,10 @@ | ||||||
|                         class: themeSwitcher.currentTheme, |                         class: themeSwitcher.currentTheme, | ||||||
|                         okText: '{{ i18n "reset"}}', |                         okText: '{{ i18n "reset"}}', | ||||||
|                         cancelText: '{{ i18n "cancel"}}', |                         cancelText: '{{ i18n "cancel"}}', | ||||||
|                         onOk: () => this.submit('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email), |                         onOk: () => this.submit('/panel/api/inbounds/' + dbInboundId + '/resetClientTraffic/' + client.email), | ||||||
|                     }) |                     }) | ||||||
|                 } else { |                 } else { | ||||||
|                     this.submit('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email); |                     this.submit('/panel/api/inbounds/' + dbInboundId + '/resetClientTraffic/' + client.email); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             resetAllTraffic() { |             resetAllTraffic() { | ||||||
|  | @ -1396,7 +1396,7 @@ | ||||||
|                     class: themeSwitcher.currentTheme, |                     class: themeSwitcher.currentTheme, | ||||||
|                     okText: '{{ i18n "reset"}}', |                     okText: '{{ i18n "reset"}}', | ||||||
|                     cancelText: '{{ i18n "cancel"}}', |                     cancelText: '{{ i18n "cancel"}}', | ||||||
|                     onOk: () => this.submit('/panel/inbound/resetAllTraffics'), |                     onOk: () => this.submit('/panel/api/inbounds/resetAllTraffics'), | ||||||
|                 }); |                 }); | ||||||
|             }, |             }, | ||||||
|             resetAllClientTraffics(dbInboundId) { |             resetAllClientTraffics(dbInboundId) { | ||||||
|  | @ -1406,7 +1406,7 @@ | ||||||
|                     class: themeSwitcher.currentTheme, |                     class: themeSwitcher.currentTheme, | ||||||
|                     okText: '{{ i18n "reset"}}', |                     okText: '{{ i18n "reset"}}', | ||||||
|                     cancelText: '{{ i18n "cancel"}}', |                     cancelText: '{{ i18n "cancel"}}', | ||||||
|                     onOk: () => this.submit('/panel/inbound/resetAllClientTraffics/' + dbInboundId), |                     onOk: () => this.submit('/panel/api/inbounds/resetAllClientTraffics/' + dbInboundId), | ||||||
|                 }) |                 }) | ||||||
|             }, |             }, | ||||||
|             delDepletedClients(dbInboundId) { |             delDepletedClients(dbInboundId) { | ||||||
|  | @ -1416,7 +1416,7 @@ | ||||||
|                     class: themeSwitcher.currentTheme, |                     class: themeSwitcher.currentTheme, | ||||||
|                     okText: '{{ i18n "delete"}}', |                     okText: '{{ i18n "delete"}}', | ||||||
|                     cancelText: '{{ i18n "cancel"}}', |                     cancelText: '{{ i18n "cancel"}}', | ||||||
|                     onOk: () => this.submit('/panel/inbound/delDepletedClients/' + dbInboundId), |                     onOk: () => this.submit('/panel/api/inbounds/delDepletedClients/' + dbInboundId), | ||||||
|                 }) |                 }) | ||||||
|             }, |             }, | ||||||
|             isExpiry(dbInbound, index) { |             isExpiry(dbInbound, index) { | ||||||
|  | @ -1542,7 +1542,7 @@ | ||||||
|                     value: '', |                     value: '', | ||||||
|                     okText: '{{ i18n "pages.inbounds.import" }}', |                     okText: '{{ i18n "pages.inbounds.import" }}', | ||||||
|                     confirm: async (dbInboundText) => { |                     confirm: async (dbInboundText) => { | ||||||
|                         await this.submit('/panel/inbound/import', {data: dbInboundText}, promptModal); |                         await this.submit('/panel/api/inbounds/import', {data: dbInboundText}, promptModal); | ||||||
|                     }, |                     }, | ||||||
|                 }); |                 }); | ||||||
|             }, |             }, | ||||||
|  |  | ||||||
|  | @ -746,7 +746,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async getStatus() { |             async getStatus() { | ||||||
|                 try { |                 try { | ||||||
|                     const msg = await HttpUtil.post('/server/status'); |                     const msg = await HttpUtil.get('/panel/api/server/status'); | ||||||
|                     if (msg.success) { |                     if (msg.success) { | ||||||
|                         if (!this.loadingStates.fetched) { |                         if (!this.loadingStates.fetched) { | ||||||
|                             this.loadingStates.fetched = true; |                             this.loadingStates.fetched = true; | ||||||
|  | @ -763,7 +763,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async openSelectV2rayVersion() { |             async openSelectV2rayVersion() { | ||||||
|                 this.loading(true); |                 this.loading(true); | ||||||
|                 const msg = await HttpUtil.post('server/getXrayVersion'); |                 const msg = await HttpUtil.get('/panel/api/server/getXrayVersion'); | ||||||
|                 this.loading(false); |                 this.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -780,7 +780,7 @@ ${dateTime} | ||||||
|                     onOk: async () => { |                     onOk: async () => { | ||||||
|                         versionModal.hide(); |                         versionModal.hide(); | ||||||
|                         this.loading(true, '{{ i18n "pages.index.dontRefresh"}}'); |                         this.loading(true, '{{ i18n "pages.index.dontRefresh"}}'); | ||||||
|                         await HttpUtil.post(`/server/installXray/${version}`); |                         await HttpUtil.post(`/panel/api/server/installXray/${version}`); | ||||||
|                         this.loading(false); |                         this.loading(false); | ||||||
|                     }, |                     }, | ||||||
|                 }); |                 }); | ||||||
|  | @ -798,9 +798,9 @@ ${dateTime} | ||||||
|                     onOk: async () => { |                     onOk: async () => { | ||||||
|                         versionModal.hide(); |                         versionModal.hide(); | ||||||
|                         this.loading(true, '{{ i18n "pages.index.dontRefresh"}}'); |                         this.loading(true, '{{ i18n "pages.index.dontRefresh"}}'); | ||||||
|                         const url = isSingleFile  |                         const url = isSingleFile | ||||||
|                             ? `/server/updateGeofile/${fileName}`  |                             ? `/panel/api/server/updateGeofile/${fileName}` | ||||||
|                             : `/server/updateGeofile`; |                             : `/panel/api/server/updateGeofile`; | ||||||
|                         await HttpUtil.post(url); |                         await HttpUtil.post(url); | ||||||
|                         this.loading(false); |                         this.loading(false); | ||||||
|                     }, |                     }, | ||||||
|  | @ -808,7 +808,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async stopXrayService() { |             async stopXrayService() { | ||||||
|                 this.loading(true); |                 this.loading(true); | ||||||
|                 const msg = await HttpUtil.post('server/stopXrayService'); |                 const msg = await HttpUtil.post('/panel/api/server/stopXrayService'); | ||||||
|                 this.loading(false); |                 this.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -816,7 +816,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async restartXrayService() { |             async restartXrayService() { | ||||||
|                 this.loading(true); |                 this.loading(true); | ||||||
|                 const msg = await HttpUtil.post('server/restartXrayService'); |                 const msg = await HttpUtil.post('/panel/api/server/restartXrayService'); | ||||||
|                 this.loading(false); |                 this.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -824,7 +824,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async openLogs(){ |             async openLogs(){ | ||||||
|                 logModal.loading = true; |                 logModal.loading = true; | ||||||
|                 const msg = await HttpUtil.post('server/logs/'+logModal.rows,{level: logModal.level, syslog: logModal.syslog}); |                 const msg = await HttpUtil.post('/panel/api/server/logs/'+logModal.rows,{level: logModal.level, syslog: logModal.syslog}); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  | @ -834,7 +834,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async openXrayLogs(){ |             async openXrayLogs(){ | ||||||
|               xraylogModal.loading = true; |               xraylogModal.loading = true; | ||||||
|                 const msg = await HttpUtil.post('server/xraylogs/'+xraylogModal.rows,{filter: xraylogModal.filter, showDirect: xraylogModal.showDirect, showBlocked: xraylogModal.showBlocked, showProxy: xraylogModal.showProxy}); |                 const msg = await HttpUtil.post('/panel/api/server/xraylogs/'+xraylogModal.rows,{filter: xraylogModal.filter, showDirect: xraylogModal.showDirect, showBlocked: xraylogModal.showBlocked, showProxy: xraylogModal.showProxy}); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  | @ -844,7 +844,7 @@ ${dateTime} | ||||||
|             }, |             }, | ||||||
|             async openConfig() { |             async openConfig() { | ||||||
|                 this.loading(true); |                 this.loading(true); | ||||||
|                 const msg = await HttpUtil.post('server/getConfigJson'); |                 const msg = await HttpUtil.get('/panel/api/server/getConfigJson'); | ||||||
|                 this.loading(false); |                 this.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -855,7 +855,7 @@ ${dateTime} | ||||||
|               backupModal.show(); |               backupModal.show(); | ||||||
|             }, |             }, | ||||||
|             exportDatabase() { |             exportDatabase() { | ||||||
|                 window.location = basePath + 'server/getDb'; |                 window.location = basePath + 'panel/api/server/getDb'; | ||||||
|             }, |             }, | ||||||
|             importDatabase() { |             importDatabase() { | ||||||
|                 const fileInput = document.createElement('input'); |                 const fileInput = document.createElement('input'); | ||||||
|  | @ -868,7 +868,7 @@ ${dateTime} | ||||||
|                         formData.append('db', dbFile); |                         formData.append('db', dbFile); | ||||||
|                         backupModal.hide(); |                         backupModal.hide(); | ||||||
|                         this.loading(true); |                         this.loading(true); | ||||||
|                         const uploadMsg = await HttpUtil.post('server/importDB', formData, { |                         const uploadMsg = await HttpUtil.post('/panel/api/server/importDB', formData, { | ||||||
|                             headers: { |                             headers: { | ||||||
|                                 'Content-Type': 'multipart/form-data', |                                 'Content-Type': 'multipart/form-data', | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
|  | @ -121,7 +121,7 @@ | ||||||
|         }, |         }, | ||||||
|         methods: { |         methods: { | ||||||
|             async getDBClientIps(email) { |             async getDBClientIps(email) { | ||||||
|                 const msg = await HttpUtil.post(`/panel/inbound/clientIps/${email}`); |                 const msg = await HttpUtil.post(`/panel/api/inbounds/clientIps/${email}`); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     document.getElementById("clientIPs").value = msg.obj; |                     document.getElementById("clientIPs").value = msg.obj; | ||||||
|                     return; |                     return; | ||||||
|  | @ -139,7 +139,7 @@ | ||||||
|             }, |             }, | ||||||
|             async clearDBClientIps(email) { |             async clearDBClientIps(email) { | ||||||
|                 try { |                 try { | ||||||
|                     const msg = await HttpUtil.post(`/panel/inbound/clearClientIps/${email}`); |                     const msg = await HttpUtil.post(`/panel/api/inbounds/clearClientIps/${email}`); | ||||||
|                     if (!msg.success) { |                     if (!msg.success) { | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|  | @ -156,7 +156,7 @@ | ||||||
|                     cancelText: '{{ i18n "cancel"}}', |                     cancelText: '{{ i18n "cancel"}}', | ||||||
|                     onOk: async () => { |                     onOk: async () => { | ||||||
|                         iconElement.disabled = true; |                         iconElement.disabled = true; | ||||||
|                         const msg = await HttpUtil.postWithModal('/panel/inbound/' + dbInboundId + '/resetClientTraffic/' + email); |                         const msg = await HttpUtil.postWithModal('/panel/api/inbounds/' + dbInboundId + '/resetClientTraffic/' + email); | ||||||
|                         if (msg.success) { |                         if (msg.success) { | ||||||
|                             this.clientModal.clientStats.up = 0; |                             this.clientModal.clientStats.up = 0; | ||||||
|                             this.clientModal.clientStats.down = 0; |                             this.clientModal.clientStats.down = 0; | ||||||
|  |  | ||||||
|  | @ -492,7 +492,7 @@ | ||||||
| </a-modal> | </a-modal> | ||||||
| <script> | <script> | ||||||
|   function refreshIPs(email) { |   function refreshIPs(email) { | ||||||
|     return HttpUtil.post(`/panel/inbound/clientIps/${email}`).then((msg) => { |     return HttpUtil.post(`/panel/api/inbounds/clientIps/${email}`).then((msg) => { | ||||||
|       if (msg.success) { |       if (msg.success) { | ||||||
|         try { |         try { | ||||||
|           return JSON.parse(msg.obj).join(', '); |           return JSON.parse(msg.obj).join(', '); | ||||||
|  | @ -613,7 +613,7 @@ | ||||||
|           }); |           }); | ||||||
|       }, |       }, | ||||||
|       clearClientIps() { |       clearClientIps() { | ||||||
|         HttpUtil.post(`/panel/inbound/clearClientIps/${this.infoModal.clientStats.email}`) |         HttpUtil.post(`/panel/api/inbounds/clearClientIps/${this.infoModal.clientStats.email}`) | ||||||
|           .then((msg) => { |           .then((msg) => { | ||||||
|             if (!msg.success) { |             if (!msg.success) { | ||||||
|               return; |               return; | ||||||
|  |  | ||||||
|  | @ -132,7 +132,7 @@ | ||||||
|             }, |             }, | ||||||
|             async getNewX25519Cert() { |             async getNewX25519Cert() { | ||||||
|                 inModal.loading(true); |                 inModal.loading(true); | ||||||
|                 const msg = await HttpUtil.post('/server/getNewX25519Cert'); |                 const msg = await HttpUtil.get('/panel/api/server/getNewX25519Cert'); | ||||||
|                 inModal.loading(false); |                 inModal.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -146,7 +146,7 @@ | ||||||
|             }, |             }, | ||||||
|             async getNewmldsa65() { |             async getNewmldsa65() { | ||||||
|                 inModal.loading(true); |                 inModal.loading(true); | ||||||
|                 const msg = await HttpUtil.post('/server/getNewmldsa65'); |                 const msg = await HttpUtil.get('/panel/api/server/getNewmldsa65'); | ||||||
|                 inModal.loading(false); |                 inModal.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -160,7 +160,7 @@ | ||||||
|             }, |             }, | ||||||
|             async getNewEchCert() { |             async getNewEchCert() { | ||||||
|                 inModal.loading(true); |                 inModal.loading(true); | ||||||
|                 const msg = await HttpUtil.post('/server/getNewEchCert', { sni: inModal.inbound.stream.tls.sni }); |                 const msg = await HttpUtil.post('/panel/api/server/getNewEchCert', { sni: inModal.inbound.stream.tls.sni }); | ||||||
|                 inModal.loading(false); |                 inModal.loading(false); | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|                     return; |                     return; | ||||||
|  | @ -174,7 +174,7 @@ | ||||||
|             }, |             }, | ||||||
|             async getNewVlessEnc() { |             async getNewVlessEnc() { | ||||||
|                 inModal.loading(true); |                 inModal.loading(true); | ||||||
|                 const msg = await HttpUtil.post('/server/getNewVlessEnc'); |                 const msg = await HttpUtil.get('/panel/api/server/getNewVlessEnc'); | ||||||
|                 inModal.loading(false); |                 inModal.loading(false); | ||||||
| 
 | 
 | ||||||
|                 if (!msg.success) { |                 if (!msg.success) { | ||||||
|  |  | ||||||
|  | @ -151,7 +151,7 @@ | ||||||
|     methods: { |     methods: { | ||||||
|       async getStatus() { |       async getStatus() { | ||||||
|         try { |         try { | ||||||
|           const msg = await HttpUtil.post('/server/status'); |           const msg = await HttpUtil.get('/panel/api/server/status'); | ||||||
|           if (msg.success) { |           if (msg.success) { | ||||||
|             this.serverStatus = msg.obj; |             this.serverStatus = msg.obj; | ||||||
|           } |           } | ||||||
|  |  | ||||||
|  | @ -420,7 +420,7 @@ | ||||||
|       }, |       }, | ||||||
|       async restartXray() { |       async restartXray() { | ||||||
|         this.loading(true); |         this.loading(true); | ||||||
|         const msg = await HttpUtil.post("server/restartXrayService"); |         const msg = await HttpUtil.post("/panel/api/server/restartXrayService"); | ||||||
|         this.loading(false); |         this.loading(false); | ||||||
|         if (msg.success) { |         if (msg.success) { | ||||||
|           await PromiseUtil.sleep(500); |           await PromiseUtil.sleep(500); | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ import ( | ||||||
| 	"x-ui/util/sys" | 	"x-ui/util/sys" | ||||||
| 	"x-ui/xray" | 	"x-ui/xray" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/google/uuid" | ||||||
| 	"github.com/shirou/gopsutil/v4/cpu" | 	"github.com/shirou/gopsutil/v4/cpu" | ||||||
| 	"github.com/shirou/gopsutil/v4/disk" | 	"github.com/shirou/gopsutil/v4/disk" | ||||||
| 	"github.com/shirou/gopsutil/v4/host" | 	"github.com/shirou/gopsutil/v4/host" | ||||||
|  | @ -872,12 +873,6 @@ func (s *ServerService) GetNewEchCert(sni string) (interface{}, error) { | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type AuthBlock struct { |  | ||||||
| 	Label      string `json:"label"` |  | ||||||
| 	Decryption string `json:"decryption"` |  | ||||||
| 	Encryption string `json:"encryption"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (s *ServerService) GetNewVlessEnc() (any, error) { | func (s *ServerService) GetNewVlessEnc() (any, error) { | ||||||
| 	cmd := exec.Command(xray.GetBinaryPath(), "vlessenc") | 	cmd := exec.Command(xray.GetBinaryPath(), "vlessenc") | ||||||
| 	var out bytes.Buffer | 	var out bytes.Buffer | ||||||
|  | @ -887,37 +882,70 @@ func (s *ServerService) GetNewVlessEnc() (any, error) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	lines := strings.Split(out.String(), "\n") | 	lines := strings.Split(out.String(), "\n") | ||||||
| 
 | 	var auths []map[string]string | ||||||
| 	var blocks []AuthBlock | 	var current map[string]string | ||||||
| 	var current *AuthBlock |  | ||||||
| 
 | 
 | ||||||
| 	for _, line := range lines { | 	for _, line := range lines { | ||||||
| 		line = strings.TrimSpace(line) | 		line = strings.TrimSpace(line) | ||||||
| 		if strings.HasPrefix(line, "Authentication:") { | 		if strings.HasPrefix(line, "Authentication:") { | ||||||
| 			if current != nil { | 			if current != nil { | ||||||
| 				blocks = append(blocks, *current) | 				auths = append(auths, current) | ||||||
|  | 			} | ||||||
|  | 			current = map[string]string{ | ||||||
|  | 				"label": strings.TrimSpace(strings.TrimPrefix(line, "Authentication:")), | ||||||
| 			} | 			} | ||||||
| 			current = &AuthBlock{Label: strings.TrimSpace(strings.TrimPrefix(line, "Authentication:"))} |  | ||||||
| 		} else if strings.HasPrefix(line, `"decryption"`) || strings.HasPrefix(line, `"encryption"`) { | 		} else if strings.HasPrefix(line, `"decryption"`) || strings.HasPrefix(line, `"encryption"`) { | ||||||
| 			parts := strings.SplitN(line, ":", 2) | 			parts := strings.SplitN(line, ":", 2) | ||||||
| 			if len(parts) == 2 && current != nil { | 			if len(parts) == 2 && current != nil { | ||||||
| 				key := strings.Trim(parts[0], `" `) | 				key := strings.Trim(parts[0], `" `) | ||||||
| 				val := strings.Trim(parts[1], `" `) | 				val := strings.Trim(parts[1], `" `) | ||||||
| 				switch key { | 				current[key] = val | ||||||
| 				case "decryption": |  | ||||||
| 					current.Decryption = val |  | ||||||
| 				case "encryption": |  | ||||||
| 					current.Encryption = val |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if current != nil { | 	if current != nil { | ||||||
| 		blocks = append(blocks, *current) | 		auths = append(auths, current) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return map[string]any{ | 	return map[string]any{ | ||||||
| 		"auths": blocks, | 		"auths": auths, | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (s *ServerService) GetNewUUID() (map[string]string, error) { | ||||||
|  | 	newUUID, err := uuid.NewRandom() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to generate UUID: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return map[string]string{ | ||||||
|  | 		"uuid": newUUID.String(), | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *ServerService) GetNewmlkem768() (any, error) { | ||||||
|  | 	// Run the command
 | ||||||
|  | 	cmd := exec.Command(xray.GetBinaryPath(), "mlkem768") | ||||||
|  | 	var out bytes.Buffer | ||||||
|  | 	cmd.Stdout = &out | ||||||
|  | 	err := cmd.Run() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lines := strings.Split(out.String(), "\n") | ||||||
|  | 
 | ||||||
|  | 	SeedLine := strings.Split(lines[0], ":") | ||||||
|  | 	ClientLine := strings.Split(lines[1], ":") | ||||||
|  | 
 | ||||||
|  | 	seed := strings.TrimSpace(SeedLine[1]) | ||||||
|  | 	client := strings.TrimSpace(ClientLine[1]) | ||||||
|  | 
 | ||||||
|  | 	keyPair := map[string]any{ | ||||||
|  | 		"seed":   seed, | ||||||
|  | 		"client": client, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return keyPair, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -176,7 +176,7 @@ func (s *Server) initRouter() (*gin.Engine, error) { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	engine.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{basePath + "panel/API/"}))) | 	engine.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{basePath + "panel/api/"}))) | ||||||
| 	assetsBasePath := basePath + "assets/" | 	assetsBasePath := basePath + "assets/" | ||||||
| 
 | 
 | ||||||
| 	store := cookie.NewStore(secret) | 	store := cookie.NewStore(secret) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Sanaei
						Sanaei