| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 | 
							- package controller
 
- import (
 
- 	"encoding/json"
 
- 	"fmt"
 
- 	"strconv"
 
- 	"github.com/mhsanaei/3x-ui/v2/database/model"
 
- 	"github.com/mhsanaei/3x-ui/v2/web/service"
 
- 	"github.com/mhsanaei/3x-ui/v2/web/session"
 
- 	"github.com/gin-gonic/gin"
 
- )
 
- // InboundController handles HTTP requests related to Xray inbounds management.
 
- type InboundController struct {
 
- 	inboundService service.InboundService
 
- 	xrayService    service.XrayService
 
- }
 
- // NewInboundController creates a new InboundController and sets up its routes.
 
- func NewInboundController(g *gin.RouterGroup) *InboundController {
 
- 	a := &InboundController{}
 
- 	a.initRouter(g)
 
- 	return a
 
- }
 
- // initRouter initializes the routes for inbound-related operations.
 
- func (a *InboundController) initRouter(g *gin.RouterGroup) {
 
- 	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("/del/:id", a.delInbound)
 
- 	g.POST("/update/:id", a.updateInbound)
 
- 	g.POST("/clientIps/:email", a.getClientIps)
 
- 	g.POST("/clearClientIps/:email", a.clearClientIps)
 
- 	g.POST("/addClient", a.addInboundClient)
 
- 	g.POST("/:id/delClient/:clientId", a.delInboundClient)
 
- 	g.POST("/updateClient/:clientId", a.updateInboundClient)
 
- 	g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic)
 
- 	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)
 
- 	g.POST("/lastOnline", a.lastOnline)
 
- 	g.POST("/updateClientTraffic/:email", a.updateClientTraffic)
 
- 	g.POST("/:id/delClientByEmail/:email", a.delInboundClientByEmail)
 
- }
 
- // getInbounds retrieves the list of inbounds for the logged-in user.
 
- func (a *InboundController) getInbounds(c *gin.Context) {
 
- 	user := session.GetLoginUser(c)
 
- 	inbounds, err := a.inboundService.GetInbounds(user.Id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.obtain"), err)
 
- 		return
 
- 	}
 
- 	jsonObj(c, inbounds, nil)
 
- }
 
- // getInbound retrieves a specific inbound by its ID.
 
- func (a *InboundController) getInbound(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "get"), err)
 
- 		return
 
- 	}
 
- 	inbound, err := a.inboundService.GetInbound(id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.obtain"), err)
 
- 		return
 
- 	}
 
- 	jsonObj(c, inbound, nil)
 
- }
 
- // getClientTraffics retrieves client traffic information by email.
 
- func (a *InboundController) getClientTraffics(c *gin.Context) {
 
- 	email := c.Param("email")
 
- 	clientTraffics, err := a.inboundService.GetClientTrafficByEmail(email)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.trafficGetError"), err)
 
- 		return
 
- 	}
 
- 	jsonObj(c, clientTraffics, nil)
 
- }
 
- // getClientTrafficsById retrieves client traffic information by inbound ID.
 
- func (a *InboundController) getClientTrafficsById(c *gin.Context) {
 
- 	id := c.Param("id")
 
- 	clientTraffics, err := a.inboundService.GetClientTrafficByID(id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.trafficGetError"), err)
 
- 		return
 
- 	}
 
- 	jsonObj(c, clientTraffics, nil)
 
- }
 
- // addInbound creates a new inbound configuration.
 
- func (a *InboundController) addInbound(c *gin.Context) {
 
- 	inbound := &model.Inbound{}
 
- 	err := c.ShouldBind(inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundCreateSuccess"), err)
 
- 		return
 
- 	}
 
- 	user := session.GetLoginUser(c)
 
- 	inbound.UserId = user.Id
 
- 	if inbound.Listen == "" || inbound.Listen == "0.0.0.0" || inbound.Listen == "::" || inbound.Listen == "::0" {
 
- 		inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
 
- 	} else {
 
- 		inbound.Tag = fmt.Sprintf("inbound-%v:%v", inbound.Listen, inbound.Port)
 
- 	}
 
- 	inbound, needRestart, err := a.inboundService.AddInbound(inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.toasts.inboundCreateSuccess"), inbound, nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // delInbound deletes an inbound configuration by its ID.
 
- func (a *InboundController) delInbound(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundDeleteSuccess"), err)
 
- 		return
 
- 	}
 
- 	needRestart, err := a.inboundService.DelInbound(id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.toasts.inboundDeleteSuccess"), id, nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // updateInbound updates an existing inbound configuration.
 
- func (a *InboundController) updateInbound(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	inbound := &model.Inbound{
 
- 		Id: id,
 
- 	}
 
- 	err = c.ShouldBind(inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	inbound, needRestart, err := a.inboundService.UpdateInbound(inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), inbound, nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // getClientIps retrieves the IP addresses associated with a client by email.
 
- func (a *InboundController) getClientIps(c *gin.Context) {
 
- 	email := c.Param("email")
 
- 	ips, err := a.inboundService.GetInboundClientIps(email)
 
- 	if err != nil || ips == "" {
 
- 		jsonObj(c, "No IP Record", nil)
 
- 		return
 
- 	}
 
- 	jsonObj(c, ips, nil)
 
- }
 
- // clearClientIps clears the IP addresses for a client by email.
 
- func (a *InboundController) clearClientIps(c *gin.Context) {
 
- 	email := c.Param("email")
 
- 	err := a.inboundService.ClearClientIps(email)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.updateSuccess"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.logCleanSuccess"), nil)
 
- }
 
- // addInboundClient adds a new client to an existing inbound.
 
- func (a *InboundController) addInboundClient(c *gin.Context) {
 
- 	data := &model.Inbound{}
 
- 	err := c.ShouldBind(data)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	needRestart, err := a.inboundService.AddInboundClient(data)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundClientAddSuccess"), nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // delInboundClient deletes a client from an inbound by inbound ID and client ID.
 
- func (a *InboundController) delInboundClient(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	clientId := c.Param("clientId")
 
- 	needRestart, err := a.inboundService.DelInboundClient(id, clientId)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundClientDeleteSuccess"), nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // updateInboundClient updates a client's configuration in an inbound.
 
- func (a *InboundController) updateInboundClient(c *gin.Context) {
 
- 	clientId := c.Param("clientId")
 
- 	inbound := &model.Inbound{}
 
- 	err := c.ShouldBind(inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	needRestart, err := a.inboundService.UpdateInboundClient(inbound, clientId)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundClientUpdateSuccess"), nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // resetClientTraffic resets the traffic counter for a specific client in an inbound.
 
- func (a *InboundController) resetClientTraffic(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	email := c.Param("email")
 
- 	needRestart, err := a.inboundService.ResetClientTraffic(id, email)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetInboundClientTrafficSuccess"), nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // resetAllTraffics resets all traffic counters across all inbounds.
 
- func (a *InboundController) resetAllTraffics(c *gin.Context) {
 
- 	err := a.inboundService.ResetAllTraffics()
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	} else {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllTrafficSuccess"), nil)
 
- }
 
- // resetAllClientTraffics resets traffic counters for all clients in a specific inbound.
 
- func (a *InboundController) resetAllClientTraffics(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	err = a.inboundService.ResetAllClientTraffics(id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	} else {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.resetAllClientTrafficSuccess"), nil)
 
- }
 
- // importInbound imports an inbound configuration from provided data.
 
- func (a *InboundController) importInbound(c *gin.Context) {
 
- 	inbound := &model.Inbound{}
 
- 	err := json.Unmarshal([]byte(c.PostForm("data")), inbound)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	user := session.GetLoginUser(c)
 
- 	inbound.Id = 0
 
- 	inbound.UserId = user.Id
 
- 	if inbound.Listen == "" || inbound.Listen == "0.0.0.0" || inbound.Listen == "::" || inbound.Listen == "::0" {
 
- 		inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
 
- 	} else {
 
- 		inbound.Tag = fmt.Sprintf("inbound-%v:%v", inbound.Listen, 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.toasts.inboundCreateSuccess"), inbound, err)
 
- 	if err == nil && needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
- // delDepletedClients deletes clients in an inbound who have exhausted their traffic limits.
 
- func (a *InboundController) delDepletedClients(c *gin.Context) {
 
- 	id, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	err = a.inboundService.DelDepletedClients(id)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.delDepletedClientsSuccess"), nil)
 
- }
 
- // onlines retrieves the list of currently online clients.
 
- func (a *InboundController) onlines(c *gin.Context) {
 
- 	jsonObj(c, a.inboundService.GetOnlineClients(), nil)
 
- }
 
- // lastOnline retrieves the last online timestamps for clients.
 
- func (a *InboundController) lastOnline(c *gin.Context) {
 
- 	data, err := a.inboundService.GetClientsLastOnline()
 
- 	jsonObj(c, data, err)
 
- }
 
- // updateClientTraffic updates the traffic statistics for a client by email.
 
- func (a *InboundController) updateClientTraffic(c *gin.Context) {
 
- 	email := c.Param("email")
 
- 	// Define the request structure for traffic update
 
- 	type TrafficUpdateRequest struct {
 
- 		Upload   int64 `json:"upload"`
 
- 		Download int64 `json:"download"`
 
- 	}
 
- 	var request TrafficUpdateRequest
 
- 	err := c.ShouldBindJSON(&request)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundUpdateSuccess"), err)
 
- 		return
 
- 	}
 
- 	err = a.inboundService.UpdateClientTrafficByEmail(email, request.Upload, request.Download)
 
- 	if err != nil {
 
- 		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.inboundClientUpdateSuccess"), nil)
 
- }
 
- // delInboundClientByEmail deletes a client from an inbound by email address.
 
- func (a *InboundController) delInboundClientByEmail(c *gin.Context) {
 
- 	inboundId, err := strconv.Atoi(c.Param("id"))
 
- 	if err != nil {
 
- 		jsonMsg(c, "Invalid inbound ID", err)
 
- 		return
 
- 	}
 
- 	email := c.Param("email")
 
- 	needRestart, err := a.inboundService.DelInboundClientByEmail(inboundId, email)
 
- 	if err != nil {
 
- 		jsonMsg(c, "Failed to delete client by email", err)
 
- 		return
 
- 	}
 
- 	jsonMsg(c, "Client deleted successfully", nil)
 
- 	if needRestart {
 
- 		a.xrayService.SetToNeedRestart()
 
- 	}
 
- }
 
 
  |