2023-02-09 22:18:06 +03:00
package service
import (
2023-02-18 15:37:32 +03:00
"encoding/json"
2023-02-09 22:18:06 +03:00
"fmt"
2023-04-25 18:13:37 +03:00
"strings"
2023-02-09 22:18:06 +03:00
"time"
2024-03-11 00:31:24 +03:00
2023-02-09 22:18:06 +03:00
"x-ui/database"
"x-ui/database/model"
2023-02-18 15:37:32 +03:00
"x-ui/logger"
2023-02-09 22:18:06 +03:00
"x-ui/util/common"
"x-ui/xray"
"gorm.io/gorm"
)
type InboundService struct {
2023-06-05 00:02:19 +03:00
xrayApi xray . XrayAPI
2023-02-09 22:18:06 +03:00
}
func ( s * InboundService ) GetInbounds ( userId int ) ( [ ] * model . Inbound , error ) {
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
err := db . Model ( model . Inbound { } ) . Preload ( "ClientStats" ) . Where ( "user_id = ?" , userId ) . Find ( & inbounds ) . Error
if err != nil && err != gorm . ErrRecordNotFound {
return nil , err
}
return inbounds , nil
}
func ( s * InboundService ) GetAllInbounds ( ) ( [ ] * model . Inbound , error ) {
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
err := db . Model ( model . Inbound { } ) . Preload ( "ClientStats" ) . Find ( & inbounds ) . Error
if err != nil && err != gorm . ErrRecordNotFound {
return nil , err
}
return inbounds , nil
}
2024-01-17 15:51:28 +03:00
func ( s * InboundService ) checkPortExist ( listen string , port int , ignoreId int ) ( bool , error ) {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
2024-01-17 15:51:28 +03:00
if listen == "" || listen == "0.0.0.0" || listen == "::" || listen == "::0" {
db = db . Model ( model . Inbound { } ) . Where ( "port = ?" , port )
} else {
db = db . Model ( model . Inbound { } ) .
Where ( "port = ?" , port ) .
Where (
db . Model ( model . Inbound { } ) . Where (
"listen = ?" , listen ,
) . Or (
"listen = \"\"" ,
) . Or (
"listen = \"0.0.0.0\"" ,
) . Or (
"listen = \"::\"" ,
) . Or (
"listen = \"::0\"" ) )
}
2023-02-09 22:18:06 +03:00
if ignoreId > 0 {
db = db . Where ( "id != ?" , ignoreId )
}
var count int64
err := db . Count ( & count ) . Error
if err != nil {
return false , err
}
return count > 0 , nil
}
2023-05-22 17:36:34 +03:00
func ( s * InboundService ) GetClients ( inbound * model . Inbound ) ( [ ] model . Client , error ) {
2023-02-09 22:18:06 +03:00
settings := map [ string ] [ ] model . Client { }
json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
if settings == nil {
2023-03-17 19:07:49 +03:00
return nil , fmt . Errorf ( "setting is null" )
2023-02-09 22:18:06 +03:00
}
clients := settings [ "clients" ]
if clients == nil {
return nil , nil
}
return clients , nil
}
2023-04-18 21:04:06 +03:00
func ( s * InboundService ) getAllEmails ( ) ( [ ] string , error ) {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
2023-04-18 21:04:06 +03:00
var emails [ ] string
err := db . Raw ( `
SELECT JSON_EXTRACT ( client . value , ' $ . email ' )
FROM inbounds ,
JSON_EACH ( JSON_EXTRACT ( inbounds . settings , ' $ . clients ' ) ) AS client
` ) . Scan ( & emails ) . Error
if err != nil {
return nil , err
2023-02-09 22:18:06 +03:00
}
2023-04-18 21:04:06 +03:00
return emails , nil
}
2023-02-09 22:18:06 +03:00
2023-04-18 21:04:06 +03:00
func ( s * InboundService ) contains ( slice [ ] string , str string ) bool {
for _ , s := range slice {
if s == str {
return true
2023-02-09 22:18:06 +03:00
}
2023-04-18 21:04:06 +03:00
}
return false
}
2023-02-09 22:18:06 +03:00
2023-04-18 21:04:06 +03:00
func ( s * InboundService ) checkEmailsExistForClients ( clients [ ] model . Client ) ( string , error ) {
allEmails , err := s . getAllEmails ( )
if err != nil {
return "" , err
}
var emails [ ] string
for _ , client := range clients {
if client . Email != "" {
if s . contains ( emails , client . Email ) {
return client . Email , nil
}
if s . contains ( allEmails , client . Email ) {
2023-02-09 22:18:06 +03:00
return client . Email , nil
}
2023-04-18 21:04:06 +03:00
emails = append ( emails , client . Email )
2023-02-09 22:18:06 +03:00
}
}
return "" , nil
}
func ( s * InboundService ) checkEmailExistForInbound ( inbound * model . Inbound ) ( string , error ) {
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( inbound )
2023-02-09 22:18:06 +03:00
if err != nil {
return "" , err
}
2023-04-18 21:04:06 +03:00
allEmails , err := s . getAllEmails ( )
if err != nil {
return "" , err
}
var emails [ ] string
2023-02-09 22:18:06 +03:00
for _ , client := range clients {
2023-02-18 15:37:32 +03:00
if client . Email != "" {
2023-04-18 21:04:06 +03:00
if s . contains ( emails , client . Email ) {
return client . Email , nil
}
if s . contains ( allEmails , client . Email ) {
2023-02-09 22:18:06 +03:00
return client . Email , nil
}
2023-04-18 21:04:06 +03:00
emails = append ( emails , client . Email )
2023-02-09 22:18:06 +03:00
}
}
2023-04-18 21:04:06 +03:00
return "" , nil
2023-02-09 22:18:06 +03:00
}
2023-07-18 02:10:22 +03:00
func ( s * InboundService ) AddInbound ( inbound * model . Inbound ) ( * model . Inbound , bool , error ) {
2024-01-17 15:51:28 +03:00
exist , err := s . checkPortExist ( inbound . Listen , inbound . Port , 0 )
2023-02-09 22:18:06 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-02-09 22:18:06 +03:00
}
if exist {
2023-07-18 02:10:22 +03:00
return inbound , false , common . NewError ( "Port already exists:" , inbound . Port )
2023-02-09 22:18:06 +03:00
}
existEmail , err := s . checkEmailExistForInbound ( inbound )
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-02-09 22:18:06 +03:00
}
if existEmail != "" {
2023-07-18 02:10:22 +03:00
return inbound , false , common . NewError ( "Duplicate email:" , existEmail )
2023-02-09 22:18:06 +03:00
}
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( inbound )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-03-17 19:07:49 +03:00
}
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
2023-06-05 00:02:19 +03:00
tx := db . Begin ( )
defer func ( ) {
if err == nil {
tx . Commit ( )
} else {
tx . Rollback ( )
}
} ( )
2023-02-09 22:18:06 +03:00
2023-06-05 00:02:19 +03:00
err = tx . Save ( inbound ) . Error
2023-02-09 22:18:06 +03:00
if err == nil {
2023-12-08 22:08:44 +03:00
if len ( inbound . ClientStats ) == 0 {
for _ , client := range clients {
s . AddClientStat ( tx , inbound . Id , & client )
}
2023-03-17 19:07:49 +03:00
}
2023-12-08 22:08:44 +03:00
} else {
return inbound , false , err
2023-02-09 22:18:06 +03:00
}
2023-07-18 02:10:22 +03:00
needRestart := false
if inbound . Enable {
s . xrayApi . Init ( p . GetAPIPort ( ) )
inboundJson , err1 := json . MarshalIndent ( inbound . GenXrayInboundConfig ( ) , "" , " " )
if err1 != nil {
logger . Debug ( "Unable to marshal inbound config:" , err1 )
}
err1 = s . xrayApi . AddInbound ( inboundJson )
if err1 == nil {
logger . Debug ( "New inbound added by api:" , inbound . Tag )
} else {
logger . Debug ( "Unable to add inbound by api:" , err1 )
needRestart = true
}
s . xrayApi . Close ( )
}
return inbound , needRestart , err
2023-02-09 22:18:06 +03:00
}
2023-07-18 02:10:22 +03:00
func ( s * InboundService ) DelInbound ( id int ) ( bool , error ) {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
2023-07-18 02:10:22 +03:00
var tag string
needRestart := false
result := db . Model ( model . Inbound { } ) . Select ( "tag" ) . Where ( "id = ? and enable = ?" , id , true ) . First ( & tag )
if result . Error == nil {
s . xrayApi . Init ( p . GetAPIPort ( ) )
err1 := s . xrayApi . DelInbound ( tag )
if err1 == nil {
logger . Debug ( "Inbound deleted by api:" , tag )
} else {
logger . Debug ( "Unable to delete inbound by api:" , err1 )
needRestart = true
}
s . xrayApi . Close ( )
} else {
logger . Debug ( "No enabled inbound founded to removing by api" , tag )
}
// Delete client traffics of inbounds
2023-03-17 19:07:49 +03:00
err := db . Where ( "inbound_id = ?" , id ) . Delete ( xray . ClientTraffic { } ) . Error
if err != nil {
2023-07-18 02:10:22 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-03-17 20:51:43 +03:00
inbound , err := s . GetInbound ( id )
if err != nil {
2023-07-18 02:10:22 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( inbound )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
for _ , client := range clients {
2023-03-17 21:29:08 +03:00
err := s . DelClientIPs ( db , client . Email )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
}
2023-07-18 02:10:22 +03:00
return needRestart , db . Delete ( model . Inbound { } , id ) . Error
2023-02-09 22:18:06 +03:00
}
func ( s * InboundService ) GetInbound ( id int ) ( * model . Inbound , error ) {
db := database . GetDB ( )
inbound := & model . Inbound { }
err := db . Model ( model . Inbound { } ) . First ( inbound , id ) . Error
if err != nil {
return nil , err
}
return inbound , nil
}
2023-07-18 02:10:22 +03:00
func ( s * InboundService ) UpdateInbound ( inbound * model . Inbound ) ( * model . Inbound , bool , error ) {
2024-01-17 15:51:28 +03:00
exist , err := s . checkPortExist ( inbound . Listen , inbound . Port , inbound . Id )
2023-02-09 22:18:06 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-02-09 22:18:06 +03:00
}
if exist {
2023-07-18 02:10:22 +03:00
return inbound , false , common . NewError ( "Port already exists:" , inbound . Port )
2023-02-09 22:18:06 +03:00
}
2023-02-18 15:37:32 +03:00
2023-02-09 22:18:06 +03:00
oldInbound , err := s . GetInbound ( inbound . Id )
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-02-09 22:18:06 +03:00
}
2023-06-05 00:02:19 +03:00
2023-07-18 02:10:22 +03:00
tag := oldInbound . Tag
2023-12-04 21:20:16 +03:00
db := database . GetDB ( )
tx := db . Begin ( )
defer func ( ) {
if err != nil {
tx . Rollback ( )
} else {
tx . Commit ( )
}
} ( )
err = s . updateClientTraffics ( tx , oldInbound , inbound )
2023-06-05 00:02:19 +03:00
if err != nil {
2023-07-18 02:10:22 +03:00
return inbound , false , err
2023-06-05 00:02:19 +03:00
}
2023-02-09 22:18:06 +03:00
oldInbound . Up = inbound . Up
oldInbound . Down = inbound . Down
oldInbound . Total = inbound . Total
oldInbound . Remark = inbound . Remark
oldInbound . Enable = inbound . Enable
oldInbound . ExpiryTime = inbound . ExpiryTime
oldInbound . Listen = inbound . Listen
oldInbound . Port = inbound . Port
oldInbound . Protocol = inbound . Protocol
oldInbound . Settings = inbound . Settings
oldInbound . StreamSettings = inbound . StreamSettings
oldInbound . Sniffing = inbound . Sniffing
2024-01-17 15:51:28 +03:00
if inbound . Listen == "" || inbound . Listen == "0.0.0.0" || inbound . Listen == "::" || inbound . Listen == "::0" {
2024-02-21 21:50:51 +03:00
oldInbound . Tag = fmt . Sprintf ( "inbound-%v" , inbound . Port )
2024-01-17 15:51:28 +03:00
} else {
oldInbound . Tag = fmt . Sprintf ( "inbound-%v:%v" , inbound . Listen , inbound . Port )
}
2023-07-18 02:10:22 +03:00
needRestart := false
s . xrayApi . Init ( p . GetAPIPort ( ) )
2023-07-31 19:22:28 +03:00
if s . xrayApi . DelInbound ( tag ) == nil {
2023-07-18 02:10:22 +03:00
logger . Debug ( "Old inbound deleted by api:" , tag )
2023-07-31 19:22:28 +03:00
}
if inbound . Enable {
inboundJson , err2 := json . MarshalIndent ( oldInbound . GenXrayInboundConfig ( ) , "" , " " )
if err2 != nil {
logger . Debug ( "Unable to marshal updated inbound config:" , err2 )
needRestart = true
} else {
err2 = s . xrayApi . AddInbound ( inboundJson )
if err2 == nil {
logger . Debug ( "Updated inbound added by api:" , oldInbound . Tag )
2023-07-27 11:28:12 +03:00
} else {
2023-07-31 19:22:28 +03:00
logger . Debug ( "Unable to update inbound by api:" , err2 )
needRestart = true
2023-07-18 02:10:22 +03:00
}
}
}
s . xrayApi . Close ( )
2023-12-04 21:20:16 +03:00
return inbound , needRestart , tx . Save ( oldInbound ) . Error
2023-02-09 22:18:06 +03:00
}
2023-12-04 21:20:16 +03:00
func ( s * InboundService ) updateClientTraffics ( tx * gorm . DB , oldInbound * model . Inbound , newInbound * model . Inbound ) error {
2023-06-05 00:02:19 +03:00
oldClients , err := s . GetClients ( oldInbound )
if err != nil {
return err
}
newClients , err := s . GetClients ( newInbound )
2023-04-18 21:04:06 +03:00
if err != nil {
return err
}
2023-04-19 11:25:38 +03:00
2023-06-05 00:02:19 +03:00
var emailExists bool
for _ , oldClient := range oldClients {
emailExists = false
for _ , newClient := range newClients {
if oldClient . Email == newClient . Email {
emailExists = true
break
}
}
if ! emailExists {
err = s . DelClientStat ( tx , oldClient . Email )
if err != nil {
return err
}
}
}
for _ , newClient := range newClients {
emailExists = false
for _ , oldClient := range oldClients {
if newClient . Email == oldClient . Email {
emailExists = true
break
}
}
if ! emailExists {
err = s . AddClientStat ( tx , oldInbound . Id , & newClient )
if err != nil {
return err
}
}
}
return nil
}
func ( s * InboundService ) AddInboundClient ( data * model . Inbound ) ( bool , error ) {
clients , err := s . GetClients ( data )
if err != nil {
return false , err
}
2023-04-19 11:25:38 +03:00
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( data . Settings ) , & settings )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-19 11:25:38 +03:00
interfaceClients := settings [ "clients" ] . ( [ ] interface { } )
existEmail , err := s . checkEmailsExistForClients ( clients )
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-04-19 11:25:38 +03:00
}
2023-03-17 19:07:49 +03:00
if existEmail != "" {
2023-06-05 00:02:19 +03:00
return false , common . NewError ( "Duplicate email:" , existEmail )
2023-03-17 19:07:49 +03:00
}
2023-04-18 21:04:06 +03:00
oldInbound , err := s . GetInbound ( data . Id )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-19 11:25:38 +03:00
var oldSettings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( oldInbound . Settings ) , & oldSettings )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-19 11:25:38 +03:00
oldClients := oldSettings [ "clients" ] . ( [ ] interface { } )
oldClients = append ( oldClients , interfaceClients ... )
2023-04-18 21:04:06 +03:00
2023-04-19 11:25:38 +03:00
oldSettings [ "clients" ] = oldClients
2023-04-18 21:04:06 +03:00
2023-04-19 11:25:38 +03:00
newSettings , err := json . MarshalIndent ( oldSettings , "" , " " )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-18 21:04:06 +03:00
oldInbound . Settings = string ( newSettings )
2023-03-17 19:07:49 +03:00
2023-06-05 00:02:19 +03:00
db := database . GetDB ( )
tx := db . Begin ( )
defer func ( ) {
if err != nil {
tx . Rollback ( )
} else {
tx . Commit ( )
}
} ( )
needRestart := false
s . xrayApi . Init ( p . GetAPIPort ( ) )
2023-04-18 21:04:06 +03:00
for _ , client := range clients {
if len ( client . Email ) > 0 {
2023-06-05 00:02:19 +03:00
s . AddClientStat ( tx , data . Id , & client )
2023-07-18 02:10:22 +03:00
if client . Enable {
2023-07-27 11:28:12 +03:00
cipher := ""
if oldInbound . Protocol == "shadowsocks" {
cipher = oldSettings [ "method" ] . ( string )
}
2023-07-18 02:10:22 +03:00
err1 := s . xrayApi . AddUser ( string ( oldInbound . Protocol ) , oldInbound . Tag , map [ string ] interface { } {
"email" : client . Email ,
"id" : client . ID ,
"flow" : client . Flow ,
"password" : client . Password ,
2023-07-27 11:28:12 +03:00
"cipher" : cipher ,
2023-07-18 02:10:22 +03:00
} )
if err1 == nil {
logger . Debug ( "Client added by api:" , client . Email )
} else {
2023-07-27 11:28:12 +03:00
logger . Debug ( "Error in adding client by api:" , err1 )
2023-07-18 02:10:22 +03:00
needRestart = true
}
2023-06-05 00:02:19 +03:00
}
} else {
needRestart = true
2023-03-17 19:07:49 +03:00
}
}
2023-06-05 00:02:19 +03:00
s . xrayApi . Close ( )
return needRestart , tx . Save ( oldInbound ) . Error
2023-03-17 19:07:49 +03:00
}
2023-06-05 00:02:19 +03:00
func ( s * InboundService ) DelInboundClient ( inboundId int , clientId string ) ( bool , error ) {
2023-04-24 14:37:11 +03:00
oldInbound , err := s . GetInbound ( inboundId )
if err != nil {
logger . Error ( "Load Old Data Error" )
2023-06-05 00:02:19 +03:00
return false , err
2023-04-24 14:37:11 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( oldInbound . Settings ) , & settings )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-24 14:37:11 +03:00
email := ""
client_key := "id"
if oldInbound . Protocol == "trojan" {
client_key = "password"
}
2023-05-06 19:51:14 +03:00
if oldInbound . Protocol == "shadowsocks" {
client_key = "email"
}
2023-04-24 14:37:11 +03:00
inerfaceClients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for _ , client := range inerfaceClients {
c := client . ( map [ string ] interface { } )
c_id := c [ client_key ] . ( string )
if c_id == clientId {
email = c [ "email" ] . ( string )
} else {
newClients = append ( newClients , client )
}
}
2024-01-24 20:20:58 +03:00
if len ( newClients ) == 0 {
return false , common . NewError ( "no client remained in Inbound" )
}
2023-04-24 14:37:11 +03:00
settings [ "clients" ] = newClients
newSettings , err := json . MarshalIndent ( settings , "" , " " )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-24 14:37:11 +03:00
oldInbound . Settings = string ( newSettings )
db := database . GetDB ( )
err = s . DelClientStat ( db , email )
if err != nil {
logger . Error ( "Delete stats Data Error" )
2023-06-05 00:02:19 +03:00
return false , err
2023-04-24 14:37:11 +03:00
}
2023-03-17 19:07:49 +03:00
2023-03-17 20:51:43 +03:00
err = s . DelClientIPs ( db , email )
if err != nil {
logger . Error ( "Error in delete client IPs" )
2023-06-05 00:02:19 +03:00
return false , err
}
2023-07-18 02:10:22 +03:00
needRestart := false
2023-06-05 00:02:19 +03:00
if len ( email ) > 0 {
2023-07-27 11:28:12 +03:00
s . xrayApi . Init ( p . GetAPIPort ( ) )
err1 := s . xrayApi . RemoveUser ( oldInbound . Tag , email )
if err1 == nil {
2023-06-05 00:02:19 +03:00
logger . Debug ( "Client deleted by api:" , email )
needRestart = false
2023-07-27 11:28:12 +03:00
} else {
logger . Debug ( "Unable to del client by api:" , err1 )
needRestart = true
2023-06-05 00:02:19 +03:00
}
2023-07-27 11:28:12 +03:00
s . xrayApi . Close ( )
2023-03-17 20:51:43 +03:00
}
2023-06-05 00:02:19 +03:00
return needRestart , db . Save ( oldInbound ) . Error
2023-03-17 19:07:49 +03:00
}
2023-06-05 00:02:19 +03:00
func ( s * InboundService ) UpdateInboundClient ( data * model . Inbound , clientId string ) ( bool , error ) {
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( data )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-19 11:25:38 +03:00
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( data . Settings ) , & settings )
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-04-19 11:25:38 +03:00
}
inerfaceClients := settings [ "clients" ] . ( [ ] interface { } )
2023-04-18 21:04:06 +03:00
oldInbound , err := s . GetInbound ( data . Id )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-05-22 17:36:34 +03:00
oldClients , err := s . GetClients ( oldInbound )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-25 14:08:35 +03:00
oldEmail := ""
2024-03-11 11:22:28 +03:00
newClientId := ""
2023-04-25 14:08:35 +03:00
clientIndex := 0
for index , oldClient := range oldClients {
oldClientId := ""
if oldInbound . Protocol == "trojan" {
oldClientId = oldClient . Password
2024-03-11 11:22:28 +03:00
newClientId = clients [ 0 ] . Password
2023-05-06 19:51:14 +03:00
} else if oldInbound . Protocol == "shadowsocks" {
oldClientId = oldClient . Email
2024-03-11 11:22:28 +03:00
newClientId = clients [ 0 ] . Email
2023-04-25 14:08:35 +03:00
} else {
oldClientId = oldClient . ID
2024-03-11 11:22:28 +03:00
newClientId = clients [ 0 ] . ID
2023-04-25 14:08:35 +03:00
}
if clientId == oldClientId {
oldEmail = oldClient . Email
clientIndex = index
break
}
}
2024-03-11 11:22:28 +03:00
// Validate new client ID
if newClientId == "" {
return false , common . NewError ( "empty client ID" )
}
2023-04-25 14:08:35 +03:00
if len ( clients [ 0 ] . Email ) > 0 && clients [ 0 ] . Email != oldEmail {
2023-04-18 21:04:06 +03:00
existEmail , err := s . checkEmailsExistForClients ( clients )
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-04-18 21:04:06 +03:00
}
if existEmail != "" {
2023-06-05 00:02:19 +03:00
return false , common . NewError ( "Duplicate email:" , existEmail )
2023-04-18 21:04:06 +03:00
}
}
2023-04-19 11:25:38 +03:00
var oldSettings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( oldInbound . Settings ) , & oldSettings )
2023-03-17 19:07:49 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 19:07:49 +03:00
}
2023-04-19 11:25:38 +03:00
settingsClients := oldSettings [ "clients" ] . ( [ ] interface { } )
2023-04-25 14:08:35 +03:00
settingsClients [ clientIndex ] = inerfaceClients [ 0 ]
2023-04-19 11:25:38 +03:00
oldSettings [ "clients" ] = settingsClients
2023-04-18 21:04:06 +03:00
2023-04-19 11:25:38 +03:00
newSettings , err := json . MarshalIndent ( oldSettings , "" , " " )
2023-04-18 21:04:06 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-04-18 21:04:06 +03:00
}
2023-03-17 19:07:49 +03:00
2023-04-18 21:04:06 +03:00
oldInbound . Settings = string ( newSettings )
2023-03-17 19:07:49 +03:00
db := database . GetDB ( )
2023-06-05 00:02:19 +03:00
tx := db . Begin ( )
defer func ( ) {
if err != nil {
tx . Rollback ( )
} else {
tx . Commit ( )
}
} ( )
2023-03-17 19:07:49 +03:00
2023-04-18 21:04:06 +03:00
if len ( clients [ 0 ] . Email ) > 0 {
2023-04-25 14:08:35 +03:00
if len ( oldEmail ) > 0 {
2023-12-04 21:20:16 +03:00
err = s . UpdateClientStat ( tx , oldEmail , & clients [ 0 ] )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
2023-06-07 12:15:58 +03:00
err = s . UpdateClientIPs ( tx , oldEmail , clients [ 0 ] . Email )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
2023-03-17 19:07:49 +03:00
} else {
2023-06-05 00:02:19 +03:00
s . AddClientStat ( tx , data . Id , & clients [ 0 ] )
2023-03-17 19:07:49 +03:00
}
} else {
2023-06-05 00:02:19 +03:00
err = s . DelClientStat ( tx , oldEmail )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
2023-06-07 12:15:58 +03:00
err = s . DelClientIPs ( tx , oldEmail )
2023-03-17 20:51:43 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-03-17 20:51:43 +03:00
}
2023-03-17 19:07:49 +03:00
}
2023-07-18 02:10:22 +03:00
needRestart := false
2023-06-05 00:02:19 +03:00
if len ( oldEmail ) > 0 {
2023-07-27 11:28:12 +03:00
s . xrayApi . Init ( p . GetAPIPort ( ) )
2023-07-31 19:22:28 +03:00
if s . xrayApi . RemoveUser ( oldInbound . Tag , oldEmail ) == nil {
logger . Debug ( "Old client deleted by api:" , clients [ 0 ] . Email )
}
2023-06-05 00:02:19 +03:00
if clients [ 0 ] . Enable {
2023-07-27 11:28:12 +03:00
cipher := ""
if oldInbound . Protocol == "shadowsocks" {
cipher = oldSettings [ "method" ] . ( string )
}
2023-06-05 00:02:19 +03:00
err1 := s . xrayApi . AddUser ( string ( oldInbound . Protocol ) , oldInbound . Tag , map [ string ] interface { } {
"email" : clients [ 0 ] . Email ,
"id" : clients [ 0 ] . ID ,
"flow" : clients [ 0 ] . Flow ,
"password" : clients [ 0 ] . Password ,
2023-07-27 11:28:12 +03:00
"cipher" : cipher ,
2023-06-05 00:02:19 +03:00
} )
if err1 == nil {
logger . Debug ( "Client edited by api:" , clients [ 0 ] . Email )
2023-07-27 11:28:12 +03:00
} else {
logger . Debug ( "Error in adding client by api:" , err1 )
needRestart = true
2023-06-05 00:02:19 +03:00
}
}
2023-07-27 11:28:12 +03:00
s . xrayApi . Close ( )
} else {
logger . Debug ( "Client old email not found" )
needRestart = true
2023-06-05 00:02:19 +03:00
}
return needRestart , tx . Save ( oldInbound ) . Error
2023-03-17 19:07:49 +03:00
}
2024-03-11 11:22:28 +03:00
func ( s * InboundService ) AddTraffic ( inboundTraffics [ ] * xray . Traffic , clientTraffics [ ] * xray . ClientTraffic ) ( error , bool ) {
2023-08-26 14:49:51 +03:00
var err error
2023-04-09 22:43:18 +03:00
db := database . GetDB ( )
2023-02-09 22:18:06 +03:00
tx := db . Begin ( )
2023-04-09 22:43:18 +03:00
2023-02-09 22:18:06 +03:00
defer func ( ) {
if err != nil {
tx . Rollback ( )
} else {
tx . Commit ( )
}
} ( )
2024-03-11 11:22:28 +03:00
err = s . addInboundTraffic ( tx , inboundTraffics )
2023-08-26 14:49:51 +03:00
if err != nil {
return err , false
}
err = s . addClientTraffic ( tx , clientTraffics )
if err != nil {
return err , false
}
2023-12-04 21:20:16 +03:00
needRestart0 , count , err := s . autoRenewClients ( tx )
if err != nil {
logger . Warning ( "Error in renew clients:" , err )
} else if count > 0 {
logger . Debugf ( "%v clients renewed" , count )
}
2023-08-26 14:49:51 +03:00
needRestart1 , count , err := s . disableInvalidClients ( tx )
if err != nil {
logger . Warning ( "Error in disabling invalid clients:" , err )
} else if count > 0 {
logger . Debugf ( "%v clients disabled" , count )
}
needRestart2 , count , err := s . disableInvalidInbounds ( tx )
if err != nil {
logger . Warning ( "Error in disabling invalid inbounds:" , err )
} else if count > 0 {
logger . Debugf ( "%v inbounds disabled" , count )
}
2023-12-04 21:20:16 +03:00
return nil , ( needRestart0 || needRestart1 || needRestart2 )
2023-08-26 14:49:51 +03:00
}
func ( s * InboundService ) addInboundTraffic ( tx * gorm . DB , traffics [ ] * xray . Traffic ) error {
if len ( traffics ) == 0 {
return nil
}
var err error
for _ , traffic := range traffics {
if traffic . IsInbound {
err = tx . Model ( & model . Inbound { } ) . Where ( "tag = ?" , traffic . Tag ) .
Updates ( map [ string ] interface { } {
"up" : gorm . Expr ( "up + ?" , traffic . Up ) ,
"down" : gorm . Expr ( "down + ?" , traffic . Down ) ,
} ) . Error
if err != nil {
return err
}
}
}
return nil
}
func ( s * InboundService ) addClientTraffic ( tx * gorm . DB , traffics [ ] * xray . ClientTraffic ) ( err error ) {
if len ( traffics ) == 0 {
2023-12-04 21:13:21 +03:00
// Empty onlineUsers
if p != nil {
p . SetOnlineClients ( nil )
}
2023-08-26 14:49:51 +03:00
return nil
}
2023-04-09 22:43:18 +03:00
2023-12-04 21:13:21 +03:00
var onlineClients [ ] string
2023-04-24 13:34:05 +03:00
emails := make ( [ ] string , 0 , len ( traffics ) )
for _ , traffic := range traffics {
emails = append ( emails , traffic . Email )
}
dbClientTraffics := make ( [ ] * xray . ClientTraffic , 0 , len ( traffics ) )
2023-08-26 14:49:51 +03:00
err = tx . Model ( xray . ClientTraffic { } ) . Where ( "email IN (?)" , emails ) . Find ( & dbClientTraffics ) . Error
2023-04-24 13:34:05 +03:00
if err != nil {
return err
}
2023-07-27 11:28:12 +03:00
// Avoid empty slice error
if len ( dbClientTraffics ) == 0 {
return nil
}
2023-04-24 13:34:05 +03:00
dbClientTraffics , err = s . adjustTraffics ( tx , dbClientTraffics )
if err != nil {
return err
}
for dbTraffic_index := range dbClientTraffics {
for traffic_index := range traffics {
if dbClientTraffics [ dbTraffic_index ] . Email == traffics [ traffic_index ] . Email {
dbClientTraffics [ dbTraffic_index ] . Up += traffics [ traffic_index ] . Up
dbClientTraffics [ dbTraffic_index ] . Down += traffics [ traffic_index ] . Down
2023-12-04 21:13:21 +03:00
// Add user in onlineUsers array on traffic
if traffics [ traffic_index ] . Up + traffics [ traffic_index ] . Down > 0 {
onlineClients = append ( onlineClients , traffics [ traffic_index ] . Email )
}
2023-04-24 13:34:05 +03:00
break
}
}
}
2023-12-04 21:13:21 +03:00
// Set onlineUsers
p . SetOnlineClients ( onlineClients )
2023-04-24 13:34:05 +03:00
err = tx . Save ( dbClientTraffics ) . Error
2023-04-09 22:43:18 +03:00
if err != nil {
logger . Warning ( "AddClientTraffic update data " , err )
}
return nil
}
2023-04-24 13:34:05 +03:00
func ( s * InboundService ) adjustTraffics ( tx * gorm . DB , dbClientTraffics [ ] * xray . ClientTraffic ) ( [ ] * xray . ClientTraffic , error ) {
inboundIds := make ( [ ] int , 0 , len ( dbClientTraffics ) )
for _ , dbClientTraffic := range dbClientTraffics {
if dbClientTraffic . ExpiryTime < 0 {
inboundIds = append ( inboundIds , dbClientTraffic . InboundId )
2023-03-17 01:01:14 +03:00
}
2023-04-24 13:34:05 +03:00
}
2023-03-17 19:07:49 +03:00
2023-04-24 13:34:05 +03:00
if len ( inboundIds ) > 0 {
var inbounds [ ] * model . Inbound
err := tx . Model ( model . Inbound { } ) . Where ( "id IN (?)" , inboundIds ) . Find ( & inbounds ) . Error
2023-03-17 01:01:14 +03:00
if err != nil {
2023-04-24 13:34:05 +03:00
return nil , err
2023-02-09 22:18:06 +03:00
}
2023-04-24 13:34:05 +03:00
for inbound_index := range inbounds {
settings := map [ string ] interface { } { }
json . Unmarshal ( [ ] byte ( inbounds [ inbound_index ] . Settings ) , & settings )
clients , ok := settings [ "clients" ] . ( [ ] interface { } )
if ok {
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
for traffic_index := range dbClientTraffics {
2023-04-26 12:27:49 +03:00
if dbClientTraffics [ traffic_index ] . ExpiryTime < 0 && c [ "email" ] == dbClientTraffics [ traffic_index ] . Email {
2023-04-24 13:34:05 +03:00
oldExpiryTime := c [ "expiryTime" ] . ( float64 )
newExpiryTime := ( time . Now ( ) . Unix ( ) * 1000 ) - int64 ( oldExpiryTime )
c [ "expiryTime" ] = newExpiryTime
dbClientTraffics [ traffic_index ] . ExpiryTime = newExpiryTime
break
}
2023-04-11 15:11:04 +03:00
}
2023-04-24 13:34:05 +03:00
newClients = append ( newClients , interface { } ( c ) )
2023-04-09 22:43:18 +03:00
}
2023-04-24 13:34:05 +03:00
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
return nil , err
}
2023-04-24 13:43:25 +03:00
2023-04-24 13:34:05 +03:00
inbounds [ inbound_index ] . Settings = string ( modifiedSettings )
2023-04-24 13:43:25 +03:00
}
2023-02-09 22:18:06 +03:00
}
2023-04-24 13:34:05 +03:00
err = tx . Save ( inbounds ) . Error
if err != nil {
logger . Warning ( "AddClientTraffic update inbounds " , err )
logger . Error ( inbounds )
2023-04-24 13:43:25 +03:00
}
2023-02-09 22:18:06 +03:00
}
2023-04-24 13:43:25 +03:00
2023-04-24 13:34:05 +03:00
return dbClientTraffics , nil
2023-02-09 22:18:06 +03:00
}
2023-12-04 21:20:16 +03:00
func ( s * InboundService ) autoRenewClients ( tx * gorm . DB ) ( bool , int64 , error ) {
// check for time expired
var traffics [ ] * xray . ClientTraffic
now := time . Now ( ) . Unix ( ) * 1000
var err , err1 error
err = tx . Model ( xray . ClientTraffic { } ) . Where ( "reset > 0 and expiry_time > 0 and expiry_time <= ?" , now ) . Find ( & traffics ) . Error
if err != nil {
return false , 0 , err
}
// return if there is no client to renew
if len ( traffics ) == 0 {
return false , 0 , nil
}
var inbound_ids [ ] int
var inbounds [ ] * model . Inbound
needRestart := false
var clientsToAdd [ ] struct {
protocol string
tag string
client map [ string ] interface { }
}
for _ , traffic := range traffics {
inbound_ids = append ( inbound_ids , traffic . InboundId )
}
err = tx . Model ( model . Inbound { } ) . Where ( "id IN ?" , inbound_ids ) . Find ( & inbounds ) . Error
if err != nil {
return false , 0 , err
}
for inbound_index := range inbounds {
settings := map [ string ] interface { } { }
json . Unmarshal ( [ ] byte ( inbounds [ inbound_index ] . Settings ) , & settings )
clients := settings [ "clients" ] . ( [ ] interface { } )
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
for traffic_index , traffic := range traffics {
if traffic . Email == c [ "email" ] . ( string ) {
newExpiryTime := traffic . ExpiryTime
for newExpiryTime < now {
newExpiryTime += ( int64 ( traffic . Reset ) * 86400000 )
}
c [ "expiryTime" ] = newExpiryTime
traffics [ traffic_index ] . ExpiryTime = newExpiryTime
traffics [ traffic_index ] . Down = 0
traffics [ traffic_index ] . Up = 0
if ! traffic . Enable {
traffics [ traffic_index ] . Enable = true
clientsToAdd = append ( clientsToAdd ,
struct {
protocol string
tag string
client map [ string ] interface { }
} {
protocol : string ( inbounds [ inbound_index ] . Protocol ) ,
tag : inbounds [ inbound_index ] . Tag ,
client : c ,
} )
}
clients [ client_index ] = interface { } ( c )
break
}
}
}
settings [ "clients" ] = clients
newSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
return false , 0 , err
}
inbounds [ inbound_index ] . Settings = string ( newSettings )
}
err = tx . Save ( inbounds ) . Error
if err != nil {
return false , 0 , err
}
err = tx . Save ( traffics ) . Error
if err != nil {
return false , 0 , err
}
if p != nil {
err1 = s . xrayApi . Init ( p . GetAPIPort ( ) )
if err1 != nil {
return true , int64 ( len ( traffics ) ) , nil
}
for _ , clientToAdd := range clientsToAdd {
err1 = s . xrayApi . AddUser ( clientToAdd . protocol , clientToAdd . tag , clientToAdd . client )
if err1 != nil {
needRestart = true
}
}
s . xrayApi . Close ( )
}
return needRestart , int64 ( len ( traffics ) ) , nil
}
2023-08-26 14:49:51 +03:00
func ( s * InboundService ) disableInvalidInbounds ( tx * gorm . DB ) ( bool , int64 , error ) {
2023-02-09 22:18:06 +03:00
now := time . Now ( ) . Unix ( ) * 1000
2023-07-18 02:10:22 +03:00
needRestart := false
if p != nil {
var tags [ ] string
2023-08-26 14:49:51 +03:00
err := tx . Table ( "inbounds" ) .
2023-07-18 02:10:22 +03:00
Select ( "inbounds.tag" ) .
Where ( "((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?" , now , true ) .
Scan ( & tags ) . Error
if err != nil {
return false , 0 , err
}
s . xrayApi . Init ( p . GetAPIPort ( ) )
for _ , tag := range tags {
2023-07-27 11:28:12 +03:00
err1 := s . xrayApi . DelInbound ( tag )
2024-03-11 11:16:54 +03:00
if err1 == nil {
2023-07-18 02:10:22 +03:00
logger . Debug ( "Inbound disabled by api:" , tag )
} else {
2023-07-27 11:28:12 +03:00
logger . Debug ( "Error in disabling inbound by api:" , err1 )
2023-07-18 02:10:22 +03:00
needRestart = true
}
}
s . xrayApi . Close ( )
}
2023-08-26 14:49:51 +03:00
result := tx . Model ( model . Inbound { } ) .
2023-02-09 22:18:06 +03:00
Where ( "((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?" , now , true ) .
Update ( "enable" , false )
err := result . Error
count := result . RowsAffected
2023-07-18 02:10:22 +03:00
return needRestart , count , err
2023-02-09 22:18:06 +03:00
}
2023-05-05 22:52:39 +03:00
2023-08-26 14:49:51 +03:00
func ( s * InboundService ) disableInvalidClients ( tx * gorm . DB ) ( bool , int64 , error ) {
2023-04-18 21:04:06 +03:00
now := time . Now ( ) . Unix ( ) * 1000
2023-06-05 00:02:19 +03:00
needRestart := false
if p != nil {
var results [ ] struct {
Tag string
Email string
}
2023-08-26 14:49:51 +03:00
err := tx . Table ( "inbounds" ) .
2023-06-05 00:02:19 +03:00
Select ( "inbounds.tag, client_traffics.email" ) .
Joins ( "JOIN client_traffics ON inbounds.id = client_traffics.inbound_id" ) .
Where ( "((client_traffics.total > 0 AND client_traffics.up + client_traffics.down >= client_traffics.total) OR (client_traffics.expiry_time > 0 AND client_traffics.expiry_time <= ?)) AND client_traffics.enable = ?" , now , true ) .
Scan ( & results ) . Error
if err != nil {
return false , 0 , err
}
s . xrayApi . Init ( p . GetAPIPort ( ) )
for _ , result := range results {
2023-07-27 11:28:12 +03:00
err1 := s . xrayApi . RemoveUser ( result . Tag , result . Email )
if err1 == nil {
2023-07-18 02:10:22 +03:00
logger . Debug ( "Client disabled by api:" , result . Email )
2023-06-05 00:02:19 +03:00
} else {
2023-07-27 11:28:12 +03:00
logger . Debug ( "Error in disabling client by api:" , err1 )
2023-06-05 00:02:19 +03:00
needRestart = true
}
}
s . xrayApi . Close ( )
}
2023-08-26 14:49:51 +03:00
result := tx . Model ( xray . ClientTraffic { } ) .
2023-04-18 21:04:06 +03:00
Where ( "((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?" , now , true ) .
Update ( "enable" , false )
err := result . Error
count := result . RowsAffected
2023-06-05 00:02:19 +03:00
return needRestart , count , err
2023-04-18 21:04:06 +03:00
}
2023-05-05 22:52:39 +03:00
2023-12-05 20:13:36 +03:00
func ( s * InboundService ) GetInboundTags ( ) ( string , error ) {
db := database . GetDB ( )
var inboundTags [ ] string
err := db . Model ( model . Inbound { } ) . Select ( "tag" ) . Find ( & inboundTags ) . Error
if err != nil && err != gorm . ErrRecordNotFound {
return "" , err
}
2023-12-08 21:44:52 +03:00
tags , _ := json . Marshal ( inboundTags )
return string ( tags ) , nil
2023-12-05 20:13:36 +03:00
}
2023-05-05 22:52:39 +03:00
func ( s * InboundService ) MigrationRemoveOrphanedTraffics ( ) {
2023-04-13 18:15:18 +03:00
db := database . GetDB ( )
db . Exec ( `
DELETE FROM client_traffics
WHERE email NOT IN (
SELECT JSON_EXTRACT ( client . value , ' $ . email ' )
FROM inbounds ,
JSON_EACH ( JSON_EXTRACT ( inbounds . settings , ' $ . clients ' ) ) AS client
)
` )
}
2023-05-05 22:52:39 +03:00
2023-06-05 00:02:19 +03:00
func ( s * InboundService ) AddClientStat ( tx * gorm . DB , inboundId int , client * model . Client ) error {
2023-03-17 19:07:49 +03:00
clientTraffic := xray . ClientTraffic { }
clientTraffic . InboundId = inboundId
clientTraffic . Email = client . Email
clientTraffic . Total = client . TotalGB
clientTraffic . ExpiryTime = client . ExpiryTime
clientTraffic . Enable = true
clientTraffic . Up = 0
clientTraffic . Down = 0
2023-12-04 21:20:16 +03:00
clientTraffic . Reset = client . Reset
2023-06-05 00:02:19 +03:00
result := tx . Create ( & clientTraffic )
2023-03-17 19:07:49 +03:00
err := result . Error
2024-03-12 17:05:17 +03:00
return err
2023-02-09 22:18:06 +03:00
}
2023-05-05 22:52:39 +03:00
2023-12-04 21:20:16 +03:00
func ( s * InboundService ) UpdateClientStat ( tx * gorm . DB , email string , client * model . Client ) error {
result := tx . Model ( xray . ClientTraffic { } ) .
2023-03-17 19:07:49 +03:00
Where ( "email = ?" , email ) .
Updates ( map [ string ] interface { } {
"enable" : true ,
"email" : client . Email ,
"total" : client . TotalGB ,
2023-12-04 21:20:16 +03:00
"expiry_time" : client . ExpiryTime ,
2024-03-11 00:31:24 +03:00
"reset" : client . Reset ,
} )
2023-03-17 19:07:49 +03:00
err := result . Error
2024-03-12 17:05:17 +03:00
return err
2023-02-28 22:54:29 +03:00
}
2023-03-17 20:51:43 +03:00
func ( s * InboundService ) UpdateClientIPs ( tx * gorm . DB , oldEmail string , newEmail string ) error {
return tx . Model ( model . InboundClientIps { } ) . Where ( "client_email = ?" , oldEmail ) . Update ( "client_email" , newEmail ) . Error
}
2023-03-17 19:07:49 +03:00
func ( s * InboundService ) DelClientStat ( tx * gorm . DB , email string ) error {
2023-03-17 21:29:08 +03:00
return tx . Where ( "email = ?" , email ) . Delete ( xray . ClientTraffic { } ) . Error
2023-03-17 20:51:43 +03:00
}
func ( s * InboundService ) DelClientIPs ( tx * gorm . DB , email string ) error {
2023-03-17 21:29:08 +03:00
logger . Warning ( email )
return tx . Where ( "client_email = ?" , email ) . Delete ( model . InboundClientIps { } ) . Error
2023-03-17 19:07:49 +03:00
}
2023-05-14 21:37:49 +03:00
func ( s * InboundService ) GetClientInboundByTrafficID ( trafficId int ) ( traffic * xray . ClientTraffic , inbound * model . Inbound , err error ) {
db := database . GetDB ( )
var traffics [ ] * xray . ClientTraffic
err = db . Model ( xray . ClientTraffic { } ) . Where ( "id = ?" , trafficId ) . Find ( & traffics ) . Error
if err != nil {
logger . Warning ( err )
return nil , nil , err
}
if len ( traffics ) > 0 {
inbound , err = s . GetInbound ( traffics [ 0 ] . InboundId )
return traffics [ 0 ] , inbound , err
}
return nil , nil , nil
}
2023-05-05 17:50:56 +03:00
func ( s * InboundService ) GetClientInboundByEmail ( email string ) ( traffic * xray . ClientTraffic , inbound * model . Inbound , err error ) {
2023-05-05 00:46:43 +03:00
db := database . GetDB ( )
2023-05-05 04:04:39 +03:00
var traffics [ ] * xray . ClientTraffic
err = db . Model ( xray . ClientTraffic { } ) . Where ( "email = ?" , email ) . Find ( & traffics ) . Error
if err != nil {
logger . Warning ( err )
2023-05-05 17:50:56 +03:00
return nil , nil , err
2023-05-05 04:04:39 +03:00
}
if len ( traffics ) > 0 {
2023-05-05 17:50:56 +03:00
inbound , err = s . GetInbound ( traffics [ 0 ] . InboundId )
return traffics [ 0 ] , inbound , err
}
return nil , nil , nil
}
2023-05-14 21:37:49 +03:00
func ( s * InboundService ) GetClientByEmail ( clientEmail string ) ( * xray . ClientTraffic , * model . Client , error ) {
traffic , inbound , err := s . GetClientInboundByEmail ( clientEmail )
if err != nil {
return nil , nil , err
}
if inbound == nil {
return nil , nil , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
}
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( inbound )
2023-05-14 21:37:49 +03:00
if err != nil {
return nil , nil , err
}
for _ , client := range clients {
if client . Email == clientEmail {
return traffic , & client , nil
}
}
return nil , nil , common . NewError ( "Client Not Found In Inbound For Email:" , clientEmail )
}
2024-03-15 21:13:20 +03:00
func ( s * InboundService ) SetClientTelegramUserID ( trafficId int , tgId string ) ( bool , error ) {
2023-05-14 21:37:49 +03:00
traffic , inbound , err := s . GetClientInboundByTrafficID ( trafficId )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-14 21:37:49 +03:00
}
if inbound == nil {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Inbound Not Found For Traffic ID:" , trafficId )
2023-05-14 21:37:49 +03:00
}
clientEmail := traffic . Email
2023-05-22 17:36:34 +03:00
oldClients , err := s . GetClients ( inbound )
2023-05-14 21:37:49 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-14 21:37:49 +03:00
}
clientId := ""
for _ , oldClient := range oldClients {
if oldClient . Email == clientEmail {
if inbound . Protocol == "trojan" {
clientId = oldClient . Password
2024-01-01 18:07:56 +03:00
} else if inbound . Protocol == "shadowsocks" {
clientId = oldClient . Email
2023-05-14 21:37:49 +03:00
} else {
clientId = oldClient . ID
}
break
}
}
if len ( clientId ) == 0 {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Client Not Found For Email:" , clientEmail )
2023-05-14 21:37:49 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-14 21:37:49 +03:00
}
clients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
if c [ "email" ] == clientEmail {
c [ "tgId" ] = tgId
newClients = append ( newClients , interface { } ( c ) )
}
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-14 21:37:49 +03:00
}
inbound . Settings = string ( modifiedSettings )
2024-03-15 21:13:20 +03:00
needRestart , err := s . UpdateInboundClient ( inbound , clientId )
return needRestart , err
2023-05-14 21:37:49 +03:00
}
2024-01-01 18:07:56 +03:00
func ( s * InboundService ) checkIsEnabledByEmail ( clientEmail string ) ( bool , error ) {
_ , inbound , err := s . GetClientInboundByEmail ( clientEmail )
if err != nil {
return false , err
}
if inbound == nil {
return false , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
}
clients , err := s . GetClients ( inbound )
if err != nil {
return false , err
}
isEnable := false
for _ , client := range clients {
if client . Email == clientEmail {
isEnable = client . Enable
break
}
}
return isEnable , err
}
2024-03-15 21:13:20 +03:00
func ( s * InboundService ) ToggleClientEnableByEmail ( clientEmail string ) ( bool , bool , error ) {
2023-05-05 19:20:40 +03:00
_ , inbound , err := s . GetClientInboundByEmail ( clientEmail )
2023-05-05 17:50:56 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , false , err
2023-05-05 17:50:56 +03:00
}
2023-05-05 19:20:40 +03:00
if inbound == nil {
2024-03-15 21:13:20 +03:00
return false , false , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
2023-05-05 17:50:56 +03:00
}
2023-05-22 17:36:34 +03:00
oldClients , err := s . GetClients ( inbound )
2023-05-05 17:50:56 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , false , err
2023-05-05 17:50:56 +03:00
}
clientId := ""
2023-05-05 19:20:40 +03:00
clientOldEnabled := false
2023-05-05 17:50:56 +03:00
for _ , oldClient := range oldClients {
if oldClient . Email == clientEmail {
if inbound . Protocol == "trojan" {
clientId = oldClient . Password
2024-01-01 18:07:56 +03:00
} else if inbound . Protocol == "shadowsocks" {
clientId = oldClient . Email
2023-05-05 17:50:56 +03:00
} else {
clientId = oldClient . ID
}
2023-05-05 19:20:40 +03:00
clientOldEnabled = oldClient . Enable
2023-05-05 17:50:56 +03:00
break
}
}
if len ( clientId ) == 0 {
2024-03-15 21:13:20 +03:00
return false , false , common . NewError ( "Client Not Found For Email:" , clientEmail )
2023-05-05 17:50:56 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , false , err
2023-05-05 17:50:56 +03:00
}
clients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
if c [ "email" ] == clientEmail {
2023-05-05 19:20:40 +03:00
c [ "enable" ] = ! clientOldEnabled
2023-05-05 17:50:56 +03:00
newClients = append ( newClients , interface { } ( c ) )
}
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , false , err
2023-05-05 17:50:56 +03:00
}
inbound . Settings = string ( modifiedSettings )
2023-06-05 00:02:19 +03:00
2024-03-15 21:13:20 +03:00
needRestart , err := s . UpdateInboundClient ( inbound , clientId )
2023-06-05 00:02:19 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , needRestart , err
2023-06-05 00:02:19 +03:00
}
2024-03-15 21:13:20 +03:00
return ! clientOldEnabled , needRestart , nil
2023-05-05 17:50:56 +03:00
}
2024-03-15 21:13:20 +03:00
func ( s * InboundService ) ResetClientIpLimitByEmail ( clientEmail string , count int ) ( bool , error ) {
2023-05-05 19:20:40 +03:00
_ , inbound , err := s . GetClientInboundByEmail ( clientEmail )
2023-05-05 17:50:56 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 17:50:56 +03:00
}
2023-05-05 19:20:40 +03:00
if inbound == nil {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
2023-05-05 17:50:56 +03:00
}
2023-05-22 17:36:34 +03:00
oldClients , err := s . GetClients ( inbound )
2023-05-05 17:50:56 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 17:50:56 +03:00
}
clientId := ""
for _ , oldClient := range oldClients {
if oldClient . Email == clientEmail {
if inbound . Protocol == "trojan" {
clientId = oldClient . Password
2024-01-01 18:07:56 +03:00
} else if inbound . Protocol == "shadowsocks" {
clientId = oldClient . Email
2023-05-05 17:50:56 +03:00
} else {
clientId = oldClient . ID
}
break
}
}
if len ( clientId ) == 0 {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Client Not Found For Email:" , clientEmail )
2023-05-05 17:50:56 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 17:50:56 +03:00
}
clients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
if c [ "email" ] == clientEmail {
c [ "limitIp" ] = count
newClients = append ( newClients , interface { } ( c ) )
}
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 04:04:39 +03:00
}
2023-05-05 17:50:56 +03:00
inbound . Settings = string ( modifiedSettings )
2024-03-15 21:13:20 +03:00
needRestart , err := s . UpdateInboundClient ( inbound , clientId )
return needRestart , err
2023-06-05 00:02:19 +03:00
}
2023-07-01 15:26:43 +03:00
2024-03-15 21:13:20 +03:00
func ( s * InboundService ) ResetClientExpiryTimeByEmail ( clientEmail string , expiry_time int64 ) ( bool , error ) {
2023-05-05 19:20:40 +03:00
_ , inbound , err := s . GetClientInboundByEmail ( clientEmail )
2023-05-05 04:04:39 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 04:04:39 +03:00
}
if inbound == nil {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
2023-05-05 04:04:39 +03:00
}
2023-05-05 00:46:43 +03:00
2023-05-22 17:36:34 +03:00
oldClients , err := s . GetClients ( inbound )
2023-05-05 04:04:39 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 04:04:39 +03:00
}
2023-05-05 00:46:43 +03:00
2023-05-05 04:04:39 +03:00
clientId := ""
for _ , oldClient := range oldClients {
if oldClient . Email == clientEmail {
if inbound . Protocol == "trojan" {
clientId = oldClient . Password
2024-01-01 18:07:56 +03:00
} else if inbound . Protocol == "shadowsocks" {
clientId = oldClient . Email
2023-05-05 04:04:39 +03:00
} else {
clientId = oldClient . ID
}
break
}
}
if len ( clientId ) == 0 {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Client Not Found For Email:" , clientEmail )
2023-05-05 04:04:39 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
2023-05-05 00:46:43 +03:00
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 00:46:43 +03:00
}
2023-05-05 04:04:39 +03:00
clients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
if c [ "email" ] == clientEmail {
c [ "expiryTime" ] = expiry_time
newClients = append ( newClients , interface { } ( c ) )
}
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-05-05 04:04:39 +03:00
}
inbound . Settings = string ( modifiedSettings )
2024-03-15 21:13:20 +03:00
needRestart , err := s . UpdateInboundClient ( inbound , clientId )
return needRestart , err
2023-05-05 00:46:43 +03:00
}
2024-03-15 21:13:20 +03:00
func ( s * InboundService ) ResetClientTrafficLimitByEmail ( clientEmail string , totalGB int ) ( bool , error ) {
2023-11-20 17:17:59 +03:00
if totalGB < 0 {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "totalGB must be >= 0" )
2023-11-20 17:17:59 +03:00
}
_ , inbound , err := s . GetClientInboundByEmail ( clientEmail )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-11-20 17:17:59 +03:00
}
if inbound == nil {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Inbound Not Found For Email:" , clientEmail )
2023-11-20 17:17:59 +03:00
}
oldClients , err := s . GetClients ( inbound )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-11-20 17:17:59 +03:00
}
clientId := ""
for _ , oldClient := range oldClients {
if oldClient . Email == clientEmail {
if inbound . Protocol == "trojan" {
clientId = oldClient . Password
2024-01-01 18:07:56 +03:00
} else if inbound . Protocol == "shadowsocks" {
clientId = oldClient . Email
2023-11-20 17:17:59 +03:00
} else {
clientId = oldClient . ID
}
break
}
}
if len ( clientId ) == 0 {
2024-03-15 21:13:20 +03:00
return false , common . NewError ( "Client Not Found For Email:" , clientEmail )
2023-11-20 17:17:59 +03:00
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-11-20 17:17:59 +03:00
}
clients := settings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
if c [ "email" ] == clientEmail {
c [ "totalGB" ] = totalGB * 1024 * 1024 * 1024
newClients = append ( newClients , interface { } ( c ) )
}
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
2024-03-15 21:13:20 +03:00
return false , err
2023-11-20 17:17:59 +03:00
}
inbound . Settings = string ( modifiedSettings )
2024-03-15 21:13:20 +03:00
needRestart , err := s . UpdateInboundClient ( inbound , clientId )
return needRestart , err
2023-11-20 17:17:59 +03:00
}
2023-05-05 00:46:43 +03:00
func ( s * InboundService ) ResetClientTrafficByEmail ( clientEmail string ) error {
db := database . GetDB ( )
result := db . Model ( xray . ClientTraffic { } ) .
Where ( "email = ?" , clientEmail ) .
Updates ( map [ string ] interface { } { "enable" : true , "up" : 0 , "down" : 0 } )
err := result . Error
if err != nil {
return err
}
return nil
}
2023-06-05 00:02:19 +03:00
func ( s * InboundService ) ResetClientTraffic ( id int , clientEmail string ) ( bool , error ) {
needRestart := false
2023-02-09 22:18:06 +03:00
2023-06-05 00:02:19 +03:00
traffic , err := s . GetClientTrafficByEmail ( clientEmail )
if err != nil {
return false , err
}
2023-02-28 22:54:29 +03:00
2023-06-05 00:02:19 +03:00
if ! traffic . Enable {
inbound , err := s . GetInbound ( id )
if err != nil {
return false , err
}
clients , err := s . GetClients ( inbound )
if err != nil {
return false , err
}
for _ , client := range clients {
if client . Email == clientEmail {
s . xrayApi . Init ( p . GetAPIPort ( ) )
2023-07-27 11:28:12 +03:00
cipher := ""
if string ( inbound . Protocol ) == "shadowsocks" {
var oldSettings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( inbound . Settings ) , & oldSettings )
if err != nil {
return false , err
}
cipher = oldSettings [ "method" ] . ( string )
}
2023-06-05 00:02:19 +03:00
err1 := s . xrayApi . AddUser ( string ( inbound . Protocol ) , inbound . Tag , map [ string ] interface { } {
"email" : client . Email ,
"id" : client . ID ,
"flow" : client . Flow ,
"password" : client . Password ,
2023-07-27 11:28:12 +03:00
"cipher" : cipher ,
2023-06-05 00:02:19 +03:00
} )
if err1 == nil {
logger . Debug ( "Client enabled due to reset traffic:" , clientEmail )
} else {
2023-07-27 11:28:12 +03:00
logger . Debug ( "Error in enabling client by api:" , err1 )
2023-06-05 00:02:19 +03:00
needRestart = true
}
s . xrayApi . Close ( )
break
}
}
}
traffic . Up = 0
traffic . Down = 0
traffic . Enable = true
2023-02-28 22:54:29 +03:00
2023-06-05 00:02:19 +03:00
db := database . GetDB ( )
err = db . Save ( traffic ) . Error
2023-02-28 22:54:29 +03:00
if err != nil {
2023-06-05 00:02:19 +03:00
return false , err
2023-02-28 22:54:29 +03:00
}
2023-06-05 00:02:19 +03:00
return needRestart , nil
2023-02-28 22:54:29 +03:00
}
2023-04-09 22:43:18 +03:00
func ( s * InboundService ) ResetAllClientTraffics ( id int ) error {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
2023-04-25 14:08:35 +03:00
whereText := "inbound_id "
if id == - 1 {
whereText += " > ?"
} else {
whereText += " = ?"
}
2023-04-09 22:43:18 +03:00
result := db . Model ( xray . ClientTraffic { } ) .
2023-04-25 14:08:35 +03:00
Where ( whereText , id ) .
2023-04-09 22:43:18 +03:00
Updates ( map [ string ] interface { } { "enable" : true , "up" : 0 , "down" : 0 } )
err := result . Error
2024-03-12 17:05:17 +03:00
return err
2023-04-09 22:43:18 +03:00
}
func ( s * InboundService ) ResetAllTraffics ( ) error {
db := database . GetDB ( )
result := db . Model ( model . Inbound { } ) .
Where ( "user_id > ?" , 0 ) .
Updates ( map [ string ] interface { } { "up" : 0 , "down" : 0 } )
err := result . Error
2024-03-12 17:05:17 +03:00
return err
2023-04-09 22:43:18 +03:00
}
2023-04-25 18:13:37 +03:00
func ( s * InboundService ) DelDepletedClients ( id int ) ( err error ) {
db := database . GetDB ( )
tx := db . Begin ( )
defer func ( ) {
if err == nil {
tx . Commit ( )
} else {
tx . Rollback ( )
}
} ( )
2023-12-04 21:20:16 +03:00
whereText := "reset = 0 and inbound_id "
2023-04-25 18:13:37 +03:00
if id < 0 {
whereText += "> ?"
} else {
whereText += "= ?"
}
depletedClients := [ ] xray . ClientTraffic { }
err = db . Model ( xray . ClientTraffic { } ) . Where ( whereText + " and enable = ?" , id , false ) . Select ( "inbound_id, GROUP_CONCAT(email) as email" ) . Group ( "inbound_id" ) . Find ( & depletedClients ) . Error
if err != nil {
return err
}
for _ , depletedClient := range depletedClients {
emails := strings . Split ( depletedClient . Email , "," )
oldInbound , err := s . GetInbound ( depletedClient . InboundId )
if err != nil {
return err
}
var oldSettings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( oldInbound . Settings ) , & oldSettings )
if err != nil {
return err
}
oldClients := oldSettings [ "clients" ] . ( [ ] interface { } )
var newClients [ ] interface { }
for _ , client := range oldClients {
deplete := false
c := client . ( map [ string ] interface { } )
for _ , email := range emails {
if email == c [ "email" ] . ( string ) {
deplete = true
break
}
}
if ! deplete {
newClients = append ( newClients , client )
}
}
if len ( newClients ) > 0 {
oldSettings [ "clients" ] = newClients
newSettings , err := json . MarshalIndent ( oldSettings , "" , " " )
if err != nil {
return err
}
oldInbound . Settings = string ( newSettings )
err = tx . Save ( oldInbound ) . Error
if err != nil {
return err
}
} else {
// Delete inbound if no client remains
s . DelInbound ( depletedClient . InboundId )
}
}
err = tx . Where ( whereText + " and enable = ?" , id , false ) . Delete ( xray . ClientTraffic { } ) . Error
2024-03-12 17:05:17 +03:00
return err
2023-04-25 18:13:37 +03:00
}
2024-01-01 18:07:56 +03:00
func ( s * InboundService ) GetClientTrafficTgBot ( tgId string ) ( [ ] * xray . ClientTraffic , error ) {
2023-04-09 22:43:18 +03:00
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
2024-01-01 18:07:56 +03:00
err := db . Model ( model . Inbound { } ) . Where ( "settings like ?" , fmt . Sprintf ( ` %%"tgId": "%s"%% ` , tgId ) ) . Find ( & inbounds ) . Error
2023-04-09 22:43:18 +03:00
if err != nil && err != gorm . ErrRecordNotFound {
return nil , err
}
var emails [ ] string
for _ , inbound := range inbounds {
2023-05-22 17:36:34 +03:00
clients , err := s . GetClients ( inbound )
2023-04-09 22:43:18 +03:00
if err != nil {
logger . Error ( "Unable to get clients from inbound" )
}
for _ , client := range clients {
2024-01-01 18:07:56 +03:00
if client . TgID == tgId {
2023-04-09 22:43:18 +03:00
emails = append ( emails , client . Email )
}
}
}
var traffics [ ] * xray . ClientTraffic
err = db . Model ( xray . ClientTraffic { } ) . Where ( "email IN ?" , emails ) . Find ( & traffics ) . Error
2023-03-17 19:07:49 +03:00
if err != nil {
if err == gorm . ErrRecordNotFound {
logger . Warning ( err )
return nil , err
}
}
return traffics , err
}
2023-02-09 22:18:06 +03:00
2023-04-25 14:08:35 +03:00
func ( s * InboundService ) GetClientTrafficByEmail ( email string ) ( traffic * xray . ClientTraffic , err error ) {
2023-03-17 19:07:49 +03:00
db := database . GetDB ( )
var traffics [ ] * xray . ClientTraffic
2023-02-09 22:18:06 +03:00
2023-04-21 18:36:59 +03:00
err = db . Model ( xray . ClientTraffic { } ) . Where ( "email = ?" , email ) . Find ( & traffics ) . Error
2023-02-09 22:18:06 +03:00
if err != nil {
2023-04-28 18:10:33 +03:00
logger . Warning ( err )
return nil , err
}
if len ( traffics ) > 0 {
return traffics [ 0 ] , nil
2023-02-09 22:18:06 +03:00
}
2023-04-28 18:10:33 +03:00
return nil , nil
2023-02-09 22:18:06 +03:00
}
2023-03-17 19:07:49 +03:00
func ( s * InboundService ) SearchClientTraffic ( query string ) ( traffic * xray . ClientTraffic , err error ) {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
inbound := & model . Inbound { }
traffic = & xray . ClientTraffic { }
2023-03-17 19:07:49 +03:00
err = db . Model ( model . Inbound { } ) . Where ( "settings like ?" , "%\"" + query + "\"%" ) . First ( inbound ) . Error
2023-02-09 22:18:06 +03:00
if err != nil {
if err == gorm . ErrRecordNotFound {
logger . Warning ( err )
return nil , err
}
}
traffic . InboundId = inbound . Id
// get settings clients
settings := map [ string ] [ ] model . Client { }
json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
clients := settings [ "clients" ]
for _ , client := range clients {
2023-03-17 19:07:49 +03:00
if client . ID == query && client . Email != "" {
traffic . Email = client . Email
break
}
if client . Password == query && client . Email != "" {
2023-02-09 22:18:06 +03:00
traffic . Email = client . Email
2023-03-17 19:07:49 +03:00
break
2023-02-09 22:18:06 +03:00
}
}
2023-03-17 19:07:49 +03:00
if traffic . Email == "" {
return nil , err
}
2023-02-09 22:18:06 +03:00
err = db . Model ( xray . ClientTraffic { } ) . Where ( "email = ?" , traffic . Email ) . First ( traffic ) . Error
if err != nil {
logger . Warning ( err )
return nil , err
}
return traffic , err
}
2023-03-17 20:51:43 +03:00
2023-03-17 19:07:49 +03:00
func ( s * InboundService ) GetInboundClientIps ( clientEmail string ) ( string , error ) {
db := database . GetDB ( )
InboundClientIps := & model . InboundClientIps { }
err := db . Model ( model . InboundClientIps { } ) . Where ( "client_email = ?" , clientEmail ) . First ( InboundClientIps ) . Error
if err != nil {
return "" , err
}
return InboundClientIps . Ips , nil
}
2023-05-30 23:51:14 +03:00
2023-03-17 20:51:43 +03:00
func ( s * InboundService ) ClearClientIps ( clientEmail string ) error {
2023-03-17 19:07:49 +03:00
db := database . GetDB ( )
result := db . Model ( model . InboundClientIps { } ) .
Where ( "client_email = ?" , clientEmail ) .
Update ( "ips" , "" )
err := result . Error
if err != nil {
return err
}
return nil
}
2023-03-24 16:44:26 +03:00
func ( s * InboundService ) SearchInbounds ( query string ) ( [ ] * model . Inbound , error ) {
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
err := db . Model ( model . Inbound { } ) . Preload ( "ClientStats" ) . Where ( "remark like ?" , "%" + query + "%" ) . Find ( & inbounds ) . Error
if err != nil && err != gorm . ErrRecordNotFound {
return nil , err
}
return inbounds , nil
2023-04-09 22:43:18 +03:00
}
2023-04-25 14:08:35 +03:00
2023-04-24 13:43:25 +03:00
func ( s * InboundService ) MigrationRequirements ( ) {
db := database . GetDB ( )
2023-06-05 00:02:19 +03:00
tx := db . Begin ( )
var err error
defer func ( ) {
if err == nil {
tx . Commit ( )
} else {
tx . Rollback ( )
}
} ( )
2023-04-27 18:35:36 +03:00
// Fix inbounds based problems
2023-04-24 13:43:25 +03:00
var inbounds [ ] * model . Inbound
2023-06-05 00:02:19 +03:00
err = tx . Model ( model . Inbound { } ) . Where ( "protocol IN (?)" , [ ] string { "vmess" , "vless" , "trojan" } ) . Find ( & inbounds ) . Error
2023-04-24 13:43:25 +03:00
if err != nil && err != gorm . ErrRecordNotFound {
return
}
for inbound_index := range inbounds {
settings := map [ string ] interface { } { }
json . Unmarshal ( [ ] byte ( inbounds [ inbound_index ] . Settings ) , & settings )
clients , ok := settings [ "clients" ] . ( [ ] interface { } )
if ok {
2024-02-27 14:33:37 +03:00
// Fix Client configuration problems
2023-04-24 13:43:25 +03:00
var newClients [ ] interface { }
for client_index := range clients {
c := clients [ client_index ] . ( map [ string ] interface { } )
// Add email='' if it is not exists
if _ , ok := c [ "email" ] ; ! ok {
c [ "email" ] = ""
}
// Remove "flow": "xtls-rprx-direct"
if _ , ok := c [ "flow" ] ; ok {
if c [ "flow" ] == "xtls-rprx-direct" {
c [ "flow" ] = ""
}
}
newClients = append ( newClients , interface { } ( c ) )
}
settings [ "clients" ] = newClients
modifiedSettings , err := json . MarshalIndent ( settings , "" , " " )
if err != nil {
return
}
inbounds [ inbound_index ] . Settings = string ( modifiedSettings )
}
2023-06-05 00:02:19 +03:00
2023-04-27 18:35:36 +03:00
// Add client traffic row for all clients which has email
2023-05-22 17:36:34 +03:00
modelClients , err := s . GetClients ( inbounds [ inbound_index ] )
2023-04-25 18:06:06 +03:00
if err != nil {
return
}
for _ , modelClient := range modelClients {
if len ( modelClient . Email ) > 0 {
var count int64
2023-06-05 00:02:19 +03:00
tx . Model ( xray . ClientTraffic { } ) . Where ( "email = ?" , modelClient . Email ) . Count ( & count )
2023-04-25 18:06:06 +03:00
if count == 0 {
2023-06-05 00:02:19 +03:00
s . AddClientStat ( tx , inbounds [ inbound_index ] . Id , & modelClient )
2023-04-25 18:06:06 +03:00
}
}
}
2023-04-24 13:43:25 +03:00
}
2023-06-05 00:02:19 +03:00
tx . Save ( inbounds )
2023-04-27 18:35:36 +03:00
// Remove orphaned traffics
2023-06-05 00:02:19 +03:00
tx . Where ( "inbound_id = 0" ) . Delete ( xray . ClientTraffic { } )
2023-12-08 20:45:21 +03:00
// Migrate old MultiDomain to External Proxy
var externalProxy [ ] struct {
Id int
Port int
StreamSettings [ ] byte
}
err = tx . Raw ( ` select id , port , stream_settings
from inbounds
WHERE protocol in ( ' vmess ',' vless ',' trojan ' )
AND json_extract ( stream_settings , ' $ . security ' ) = ' tls '
AND json_extract ( stream_settings , ' $ . tlsSettings . settings . domains ' ) IS NOT NULL ` ) . Scan ( & externalProxy ) . Error
if err != nil || len ( externalProxy ) == 0 {
return
}
for _ , ep := range externalProxy {
var reverses interface { }
var stream map [ string ] interface { }
json . Unmarshal ( ep . StreamSettings , & stream )
if tlsSettings , ok := stream [ "tlsSettings" ] . ( map [ string ] interface { } ) ; ok {
if settings , ok := tlsSettings [ "settings" ] . ( map [ string ] interface { } ) ; ok {
if domains , ok := settings [ "domains" ] . ( [ ] interface { } ) ; ok {
for _ , domain := range domains {
if domainMap , ok := domain . ( map [ string ] interface { } ) ; ok {
domainMap [ "forceTls" ] = "same"
domainMap [ "port" ] = ep . Port
domainMap [ "dest" ] = domainMap [ "domain" ] . ( string )
delete ( domainMap , "domain" )
}
}
}
reverses = settings [ "domains" ]
delete ( settings , "domains" )
}
}
stream [ "externalProxy" ] = reverses
newStream , _ := json . MarshalIndent ( stream , " " , " " )
tx . Model ( model . Inbound { } ) . Where ( "id = ?" , ep . Id ) . Update ( "stream_settings" , newStream )
}
2024-02-22 22:42:26 +03:00
err = tx . Raw ( ` UPDATE inbounds
SET tag = REPLACE ( tag , ' 0.0 .0 .0 : ' , ' ' )
WHERE INSTR ( tag , ' 0.0 .0 .0 : ' ) > 0 ; ` ) . Error
if err != nil {
return
}
2023-04-24 13:43:25 +03:00
}
2023-05-05 22:52:39 +03:00
func ( s * InboundService ) MigrateDB ( ) {
s . MigrationRequirements ( )
s . MigrationRemoveOrphanedTraffics ( )
}
2023-12-04 21:13:21 +03:00
func ( s * InboundService ) GetOnlineClinets ( ) [ ] string {
return p . GetOnlineClients ( )
}