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"
"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 {
}
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
}
func ( s * InboundService ) checkPortExist ( port int , ignoreId int ) ( bool , error ) {
db := database . GetDB ( )
db = db . Model ( model . Inbound { } ) . Where ( "port = ?" , port )
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
}
func ( s * InboundService ) getClients ( inbound * model . Inbound ) ( [ ] model . Client , error ) {
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 ) {
clients , err := s . getClients ( inbound )
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-02-18 15:37:32 +03:00
func ( s * InboundService ) AddInbound ( inbound * model . Inbound ) ( * model . Inbound , error ) {
2023-02-09 22:18:06 +03:00
exist , err := s . checkPortExist ( inbound . Port , 0 )
if err != nil {
return inbound , err
}
if exist {
2023-02-18 15:37:32 +03:00
return inbound , common . NewError ( "Port already exists:" , inbound . Port )
2023-02-09 22:18:06 +03:00
}
existEmail , err := s . checkEmailExistForInbound ( inbound )
if err != nil {
return inbound , err
}
if existEmail != "" {
return inbound , common . NewError ( "Duplicate email:" , existEmail )
}
2023-03-17 19:07:49 +03:00
clients , err := s . getClients ( inbound )
if err != nil {
return inbound , err
}
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
err = db . Save ( inbound ) . Error
if err == nil {
2023-03-17 19:07:49 +03:00
for _ , client := range clients {
s . AddClientStat ( inbound . Id , & client )
}
2023-02-09 22:18:06 +03:00
}
return inbound , err
}
func ( s * InboundService ) AddInbounds ( inbounds [ ] * model . Inbound ) error {
for _ , inbound := range inbounds {
exist , err := s . checkPortExist ( inbound . Port , 0 )
if err != nil {
return err
}
if exist {
2023-02-18 15:37:32 +03:00
return common . NewError ( "Port already exists:" , inbound . Port )
2023-02-09 22:18:06 +03:00
}
}
db := database . GetDB ( )
tx := db . Begin ( )
var err error
defer func ( ) {
if err == nil {
tx . Commit ( )
} else {
tx . Rollback ( )
}
} ( )
for _ , inbound := range inbounds {
err = tx . Save ( inbound ) . Error
if err != nil {
return err
}
}
return nil
}
func ( s * InboundService ) DelInbound ( id int ) error {
db := database . GetDB ( )
2023-03-17 19:07:49 +03:00
err := db . Where ( "inbound_id = ?" , id ) . Delete ( xray . ClientTraffic { } ) . Error
if err != nil {
return err
}
2023-03-17 20:51:43 +03:00
inbound , err := s . GetInbound ( id )
if err != nil {
return err
}
clients , err := s . getClients ( inbound )
if err != nil {
return err
}
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 {
return err
}
}
2023-02-09 22:18:06 +03:00
return db . Delete ( model . Inbound { } , id ) . Error
}
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
}
func ( s * InboundService ) UpdateInbound ( inbound * model . Inbound ) ( * model . Inbound , error ) {
exist , err := s . checkPortExist ( inbound . Port , inbound . Id )
if err != nil {
return inbound , err
}
if exist {
2023-02-18 15:37:32 +03:00
return inbound , 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 {
return inbound , err
}
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
oldInbound . Tag = fmt . Sprintf ( "inbound-%v" , inbound . Port )
db := database . GetDB ( )
return inbound , db . Save ( oldInbound ) . Error
}
2023-04-18 21:04:06 +03:00
func ( s * InboundService ) AddInboundClient ( data * model . Inbound ) error {
clients , err := s . getClients ( data )
if err != nil {
return 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 {
return err
}
2023-04-19 11:25:38 +03:00
interfaceClients := settings [ "clients" ] . ( [ ] interface { } )
existEmail , err := s . checkEmailsExistForClients ( clients )
if err != nil {
return err
}
2023-03-17 19:07:49 +03:00
if existEmail != "" {
return common . NewError ( "Duplicate email:" , existEmail )
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
2023-04-18 21:04:06 +03:00
oldInbound . Settings = string ( newSettings )
2023-03-17 19:07:49 +03:00
2023-04-18 21:04:06 +03:00
for _ , client := range clients {
if len ( client . Email ) > 0 {
s . AddClientStat ( data . Id , & client )
2023-03-17 19:07:49 +03:00
}
}
db := database . GetDB ( )
return db . Save ( oldInbound ) . Error
}
2023-04-24 14:37:11 +03:00
func ( s * InboundService ) DelInboundClient ( inboundId int , clientId string ) error {
oldInbound , err := s . GetInbound ( inboundId )
if err != nil {
logger . Error ( "Load Old Data Error" )
return err
}
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( oldInbound . Settings ) , & settings )
2023-03-17 19:07:49 +03:00
if err != nil {
return err
}
2023-04-24 14:37:11 +03:00
email := ""
client_key := "id"
if oldInbound . Protocol == "trojan" {
client_key = "password"
}
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 )
}
}
settings [ "clients" ] = newClients
newSettings , err := json . MarshalIndent ( settings , "" , " " )
2023-03-17 19:07:49 +03:00
if err != nil {
return err
}
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" )
return err
}
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" )
return err
}
2023-03-17 19:07:49 +03:00
return db . Save ( oldInbound ) . Error
}
2023-04-25 14:08:35 +03:00
func ( s * InboundService ) UpdateInboundClient ( data * model . Inbound , clientId string ) error {
2023-04-18 21:04:06 +03:00
clients , err := s . getClients ( data )
2023-03-17 19:07:49 +03:00
if err != nil {
return err
}
2023-04-19 11:25:38 +03:00
var settings map [ string ] interface { }
err = json . Unmarshal ( [ ] byte ( data . Settings ) , & settings )
if err != nil {
return err
}
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 {
return err
}
2023-04-18 21:04:06 +03:00
oldClients , err := s . getClients ( oldInbound )
2023-03-17 19:07:49 +03:00
if err != nil {
return err
}
2023-04-25 14:08:35 +03:00
oldEmail := ""
clientIndex := 0
for index , oldClient := range oldClients {
oldClientId := ""
if oldInbound . Protocol == "trojan" {
oldClientId = oldClient . Password
} else {
oldClientId = oldClient . ID
}
if clientId == oldClientId {
oldEmail = oldClient . Email
clientIndex = index
break
}
}
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 {
return err
}
if existEmail != "" {
return common . NewError ( "Duplicate email:" , existEmail )
}
}
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 {
return err
}
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 {
return 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
db := database . GetDB ( )
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 {
err = s . UpdateClientStat ( oldEmail , & clients [ 0 ] )
2023-03-17 20:51:43 +03:00
if err != nil {
return err
}
2023-04-25 14:08:35 +03:00
err = s . UpdateClientIPs ( db , oldEmail , clients [ 0 ] . Email )
2023-03-17 20:51:43 +03:00
if err != nil {
return err
}
2023-03-17 19:07:49 +03:00
} else {
2023-04-18 21:04:06 +03:00
s . AddClientStat ( data . Id , & clients [ 0 ] )
2023-03-17 19:07:49 +03:00
}
} else {
2023-04-25 14:08:35 +03:00
err = s . DelClientStat ( db , oldEmail )
2023-03-17 20:51:43 +03:00
if err != nil {
return err
}
2023-04-25 14:08:35 +03:00
err = s . DelClientIPs ( db , oldEmail )
2023-03-17 20:51:43 +03:00
if err != nil {
return err
}
2023-03-17 19:07:49 +03:00
}
return db . Save ( oldInbound ) . Error
}
2023-04-24 13:34:05 +03:00
func ( s * InboundService ) AddTraffic ( traffics [ ] * xray . Traffic ) error {
2023-02-09 22:18:06 +03:00
if len ( traffics ) == 0 {
return nil
}
2023-04-24 13:34:05 +03:00
// Update traffics in a single transaction
err := database . GetDB ( ) . Transaction ( func ( tx * gorm . DB ) error {
for _ , traffic := range traffics {
if traffic . IsInbound {
update := tx . Model ( & model . Inbound { } ) . Where ( "tag = ?" , traffic . Tag ) .
Updates ( map [ string ] interface { } {
"up" : gorm . Expr ( "up + ?" , traffic . Up ) ,
"down" : gorm . Expr ( "down + ?" , traffic . Down ) ,
} )
if update . Error != nil {
return update . Error
}
2023-02-09 22:18:06 +03:00
}
}
2023-04-24 13:34:05 +03:00
return nil
} )
return err
2023-02-09 22:18:06 +03:00
}
func ( s * InboundService ) AddClientTraffic ( traffics [ ] * xray . ClientTraffic ) ( err error ) {
if len ( traffics ) == 0 {
return nil
}
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 ( )
}
} ( )
2023-04-09 22:43:18 +03:00
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 ) )
err = db . Model ( xray . ClientTraffic { } ) . Where ( "email IN (?)" , emails ) . Find ( & dbClientTraffics ) . Error
if err != nil {
return err
}
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
break
}
}
}
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
}
func ( s * InboundService ) DisableInvalidInbounds ( ) ( int64 , error ) {
db := database . GetDB ( )
now := time . Now ( ) . Unix ( ) * 1000
result := db . Model ( model . Inbound { } ) .
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
return count , err
}
2023-04-18 21:04:06 +03:00
func ( s * InboundService ) DisableInvalidClients ( ) ( int64 , error ) {
db := database . GetDB ( )
now := time . Now ( ) . Unix ( ) * 1000
result := db . Model ( xray . ClientTraffic { } ) .
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
return count , err
}
2023-04-13 18:15:18 +03:00
func ( s * InboundService ) RemoveOrphanedTraffics ( ) {
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-03-17 19:07:49 +03:00
func ( s * InboundService ) AddClientStat ( inboundId int , client * model . Client ) error {
2023-02-09 22:18:06 +03:00
db := database . GetDB ( )
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
result := db . Create ( & clientTraffic )
err := result . Error
if err != nil {
return err
2023-02-09 22:18:06 +03:00
}
return nil
}
2023-03-17 19:07:49 +03:00
func ( s * InboundService ) UpdateClientStat ( email string , client * model . Client ) error {
2023-02-28 22:54:29 +03:00
db := database . GetDB ( )
2023-03-17 19:07:49 +03:00
result := db . Model ( xray . ClientTraffic { } ) .
Where ( "email = ?" , email ) .
Updates ( map [ string ] interface { } {
"enable" : true ,
"email" : client . Email ,
"total" : client . TotalGB ,
"expiry_time" : client . ExpiryTime } )
err := result . Error
2023-02-28 22:54:29 +03:00
if err != nil {
2023-03-17 19:07:49 +03:00
return err
2023-02-28 22:54:29 +03:00
}
2023-03-17 19:07:49 +03:00
return nil
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-05 00:46:43 +03:00
func ( s * InboundService ) ResetClientExpiryTimeByEmail ( clientEmail string , expiry_time int64 ) error {
db := database . GetDB ( )
result := db . Model ( xray . ClientTraffic { } ) .
Where ( "email = ?" , clientEmail ) .
Updates ( map [ string ] interface { } { "enable" : true , "expiry_time" : expiry_time } )
err := result . Error
if err != nil {
return err
}
return nil
}
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-03-17 19:07:49 +03:00
func ( s * InboundService ) ResetClientTraffic ( id int , clientEmail string ) error {
2023-02-28 22:54:29 +03:00
db := database . GetDB ( )
2023-02-09 22:18:06 +03:00
2023-03-17 19:07:49 +03:00
result := db . Model ( xray . ClientTraffic { } ) .
Where ( "inbound_id = ? and email = ?" , id , clientEmail ) .
Updates ( map [ string ] interface { } { "enable" : true , "up" : 0 , "down" : 0 } )
2023-02-28 22:54:29 +03:00
2023-03-17 19:07:49 +03:00
err := result . Error
2023-02-28 22:54:29 +03:00
if err != nil {
return err
}
return nil
}
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
if err != nil {
return err
}
return nil
}
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
if err != nil {
return err
}
return nil
}
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 ( )
}
} ( )
whereText := "inbound_id "
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
if err != nil {
return err
}
return nil
}
2023-04-09 22:43:18 +03:00
func ( s * InboundService ) GetClientTrafficTgBot ( tguname string ) ( [ ] * xray . ClientTraffic , error ) {
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
err := db . Model ( model . Inbound { } ) . Where ( "settings like ?" , fmt . Sprintf ( ` %%"tgId": "%s"%% ` , tguname ) ) . Find ( & inbounds ) . Error
if err != nil && err != gorm . ErrRecordNotFound {
return nil , err
}
var emails [ ] string
for _ , inbound := range inbounds {
clients , err := s . getClients ( inbound )
if err != nil {
logger . Error ( "Unable to get clients from inbound" )
}
for _ , client := range clients {
if client . TgID == tguname {
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-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-04-27 18:35:36 +03:00
// Fix inbounds based problems
2023-04-24 13:43:25 +03:00
var inbounds [ ] * model . Inbound
err := db . Model ( model . Inbound { } ) . Where ( "protocol IN (?)" , [ ] string { "vmess" , "vless" , "trojan" } ) . Find ( & inbounds ) . Error
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 {
2023-04-27 18:35:36 +03:00
// Fix Clinet 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-04-27 18:35:36 +03:00
// Add client traffic row for all clients which has email
2023-04-25 18:06:06 +03:00
modelClients , err := s . getClients ( inbounds [ inbound_index ] )
if err != nil {
return
}
for _ , modelClient := range modelClients {
if len ( modelClient . Email ) > 0 {
var count int64
db . Model ( xray . ClientTraffic { } ) . Where ( "email = ?" , modelClient . Email ) . Count ( & count )
if count == 0 {
s . AddClientStat ( inbounds [ inbound_index ] . Id , & modelClient )
}
}
}
2023-04-24 13:43:25 +03:00
}
db . Save ( inbounds )
2023-04-27 18:35:36 +03:00
// Remove orphaned traffics
db . Where ( "inbound_id = 0" ) . Delete ( xray . ClientTraffic { } )
2023-04-24 13:43:25 +03:00
}