mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-03-01 01:20:49 +03:00
update pack 2
This commit is contained in:
parent
fe9844b51b
commit
b412df70f1
@ -1 +1 @@
|
|||||||
1.0.5
|
1.0.6
|
@ -24,15 +24,15 @@ type User struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Inbound struct {
|
type Inbound struct {
|
||||||
Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
|
Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
|
||||||
UserId int `json:"-"`
|
UserId int `json:"-"`
|
||||||
Up int64 `json:"up" form:"up"`
|
Up int64 `json:"up" form:"up"`
|
||||||
Down int64 `json:"down" form:"down"`
|
Down int64 `json:"down" form:"down"`
|
||||||
Total int64 `json:"total" form:"total"`
|
Total int64 `json:"total" form:"total"`
|
||||||
Remark string `json:"remark" form:"remark"`
|
Remark string `json:"remark" form:"remark"`
|
||||||
Enable bool `json:"enable" form:"enable"`
|
Enable bool `json:"enable" form:"enable"`
|
||||||
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
||||||
ClientStats []xray.ClientTraffic `gorm:"foreignKey:InboundId;references:Id" json:"clientStats" form:"clientStats"`
|
ClientStats []xray.ClientTraffic `gorm:"foreignKey:InboundId;references:Id" json:"clientStats" form:"clientStats"`
|
||||||
|
|
||||||
// config part
|
// config part
|
||||||
Listen string `json:"listen" form:"listen"`
|
Listen string `json:"listen" form:"listen"`
|
||||||
@ -65,11 +65,12 @@ type Setting struct {
|
|||||||
Key string `json:"key" form:"key"`
|
Key string `json:"key" form:"key"`
|
||||||
Value string `json:"value" form:"value"`
|
Value string `json:"value" form:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
AlterIds uint16 `json:"alterId"`
|
AlterIds uint16 `json:"alterId"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Security string `json:"security"`
|
Security string `json:"security"`
|
||||||
TotalGB int64 `json:"totalGB" form:"totalGB"`
|
TotalGB int64 `json:"totalGB" form:"totalGB"`
|
||||||
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
||||||
}
|
}
|
||||||
|
15
go.mod
15
go.mod
@ -18,15 +18,14 @@ require (
|
|||||||
google.golang.org/grpc v1.53.0
|
google.golang.org/grpc v1.53.0
|
||||||
gorm.io/driver/sqlite v1.3.6
|
gorm.io/driver/sqlite v1.3.6
|
||||||
gorm.io/gorm v1.23.8
|
gorm.io/gorm v1.23.8
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-playground/locales v0.14.0 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.10.0 // indirect
|
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||||
github.com/goccy/go-json v0.10.0 // indirect
|
github.com/goccy/go-json v0.10.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/gorilla/context v1.1.1 // indirect
|
github.com/gorilla/context v1.1.1 // indirect
|
||||||
@ -35,13 +34,14 @@ require (
|
|||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
github.com/pires/go-proxyproto v0.6.2 // indirect
|
github.com/pires/go-proxyproto v0.6.2 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||||
@ -49,10 +49,9 @@ require (
|
|||||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
golang.org/x/net v0.5.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect
|
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
|
||||||
)
|
)
|
||||||
|
43
go.sum
43
go.sum
@ -25,17 +25,17 @@ github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR
|
|||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
|
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
||||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
|
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
|
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
|
||||||
@ -74,12 +74,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
|||||||
github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw=
|
github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw=
|
||||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
@ -89,8 +84,8 @@ github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
@ -107,12 +102,11 @@ github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
|
|||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
|
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@ -127,9 +121,7 @@ github.com/refraction-networking/utls v1.2.2-0.20230207151345-a75a4b484849 h1:vN
|
|||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
|
||||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
|
||||||
github.com/sagernet/sing v0.1.6 h1:Qy63OUfKpcqKjfd5rPmUlj0RGjHZSK/PJn0duyCCsRg=
|
github.com/sagernet/sing v0.1.6 h1:Qy63OUfKpcqKjfd5rPmUlj0RGjHZSK/PJn0duyCCsRg=
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7 h1:Plup6oEiyLzY3HDqQ+QsUBzgBGdVmcsgf3t8h940z9U=
|
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7 h1:Plup6oEiyLzY3HDqQ+QsUBzgBGdVmcsgf3t8h940z9U=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
@ -172,7 +164,6 @@ go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
@ -185,8 +176,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -199,10 +190,9 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
@ -212,7 +202,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
|
|||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
@ -236,17 +225,13 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
|
gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
|
||||||
|
@ -1359,7 +1359,7 @@ Inbound.VmessSettings = class extends Inbound.Settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
|
Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
|
||||||
constructor(id=RandomUtil.randomUUID(), alterId=0, email='', totalGB=0, expiryTime='') {
|
constructor(id=RandomUtil.randomUUID(), alterId=0, email=RandomUtil.randomText(), totalGB=0, expiryTime='') {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.alterId = alterId;
|
this.alterId = alterId;
|
||||||
@ -1441,7 +1441,7 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
|
|||||||
};
|
};
|
||||||
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
||||||
|
|
||||||
constructor(id=RandomUtil.randomUUID(), flow='', email='', totalGB=0, fingerprint = UTLS_FINGERPRINT.UTLS_CHROME, expiryTime='') {
|
constructor(id=RandomUtil.randomUUID(), flow='', email=RandomUtil.randomText(), totalGB=0, fingerprint = UTLS_FINGERPRINT.UTLS_CHROME, expiryTime='') {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
@ -1557,7 +1557,7 @@ Inbound.TrojanSettings = class extends Inbound.Settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
Inbound.TrojanSettings.Trojan = class extends XrayCommonClass {
|
||||||
constructor(password=RandomUtil.randomSeq(10), flow ='', email='', totalGB=0, expiryTime='') {
|
constructor(password=RandomUtil.randomSeq(10), flow ='', email=RandomUtil.randomText(), totalGB=0, expiryTime='') {
|
||||||
super();
|
super();
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
|
@ -136,6 +136,16 @@ class RandomUtil {
|
|||||||
return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
|
return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static randomText() {
|
||||||
|
var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
|
||||||
|
var string = '';
|
||||||
|
var len = 6 + Math.floor(Math.random() * 5)
|
||||||
|
for(var ii=0; ii<len; ii++){
|
||||||
|
string += chars[Math.floor(Math.random() * chars.length)];
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjectUtil {
|
class ObjectUtil {
|
||||||
|
@ -12,7 +12,7 @@ type BaseController struct {
|
|||||||
func (a *BaseController) checkLogin(c *gin.Context) {
|
func (a *BaseController) checkLogin(c *gin.Context) {
|
||||||
if !session.IsLogin(c) {
|
if !session.IsLogin(c) {
|
||||||
if isAjax(c) {
|
if isAjax(c) {
|
||||||
pureJsonMsg(c, false, I18n(c , "pages.login.loginAgain"))
|
pureJsonMsg(c, false, I18n(c, "pages.login.loginAgain"))
|
||||||
} else {
|
} else {
|
||||||
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
|
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
|
||||||
}
|
}
|
||||||
@ -22,12 +22,11 @@ func (a *BaseController) checkLogin(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func I18n(c *gin.Context, name string) string {
|
||||||
|
anyfunc, _ := c.Get("I18n")
|
||||||
|
i18n, _ := anyfunc.(func(key string, params ...string) (string, error))
|
||||||
|
|
||||||
func I18n(c *gin.Context , name string) string{
|
message, _ := i18n(name)
|
||||||
anyfunc, _ := c.Get("I18n")
|
|
||||||
i18n, _ := anyfunc.(func(key string, params ...string) (string, error))
|
|
||||||
|
|
||||||
message, _ := i18n(name)
|
return message
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,14 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"x-ui/database/model"
|
"x-ui/database/model"
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/web/global"
|
"x-ui/web/global"
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
"x-ui/web/session"
|
"x-ui/web/session"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InboundController struct {
|
type InboundController struct {
|
||||||
@ -30,9 +31,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
|
|||||||
g.POST("/add", a.addInbound)
|
g.POST("/add", a.addInbound)
|
||||||
g.POST("/del/:id", a.delInbound)
|
g.POST("/del/:id", a.delInbound)
|
||||||
g.POST("/update/:id", a.updateInbound)
|
g.POST("/update/:id", a.updateInbound)
|
||||||
|
|
||||||
g.POST("/resetClientTraffic/:email", a.resetClientTraffic)
|
g.POST("/resetClientTraffic/:email", a.resetClientTraffic)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ func (a *InboundController) getInbounds(c *gin.Context) {
|
|||||||
user := session.GetLoginUser(c)
|
user := session.GetLoginUser(c)
|
||||||
inbounds, err := a.inboundService.GetInbounds(user.Id)
|
inbounds, err := a.inboundService.GetInbounds(user.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.inbounds.toasts.obtain"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.toasts.obtain"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonObj(c, inbounds, nil)
|
jsonObj(c, inbounds, nil)
|
||||||
@ -61,12 +60,12 @@ func (a *InboundController) getInbounds(c *gin.Context) {
|
|||||||
func (a *InboundController) getInbound(c *gin.Context) {
|
func (a *InboundController) getInbound(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "get"), err)
|
jsonMsg(c, I18n(c, "get"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inbound, err := a.inboundService.GetInbound(id)
|
inbound, err := a.inboundService.GetInbound(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.inbounds.toasts.obtain"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.toasts.obtain"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonObj(c, inbound, nil)
|
jsonObj(c, inbound, nil)
|
||||||
@ -76,7 +75,7 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
|||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
err := c.ShouldBind(inbound)
|
err := c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.inbounds.addTo"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.addTo"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := session.GetLoginUser(c)
|
user := session.GetLoginUser(c)
|
||||||
@ -84,7 +83,7 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
|||||||
inbound.Enable = true
|
inbound.Enable = true
|
||||||
inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
||||||
inbound, err = a.inboundService.AddInbound(inbound)
|
inbound, err = a.inboundService.AddInbound(inbound)
|
||||||
jsonMsgObj(c, I18n(c , "pages.inbounds.addTo"), inbound, err)
|
jsonMsgObj(c, I18n(c, "pages.inbounds.addTo"), inbound, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
a.xrayService.SetToNeedRestart()
|
a.xrayService.SetToNeedRestart()
|
||||||
}
|
}
|
||||||
@ -93,11 +92,11 @@ func (a *InboundController) addInbound(c *gin.Context) {
|
|||||||
func (a *InboundController) delInbound(c *gin.Context) {
|
func (a *InboundController) delInbound(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "delete"), err)
|
jsonMsg(c, I18n(c, "delete"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = a.inboundService.DelInbound(id)
|
err = a.inboundService.DelInbound(id)
|
||||||
jsonMsgObj(c, I18n(c , "delete"), id, err)
|
jsonMsgObj(c, I18n(c, "delete"), id, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
a.xrayService.SetToNeedRestart()
|
a.xrayService.SetToNeedRestart()
|
||||||
}
|
}
|
||||||
@ -106,7 +105,7 @@ func (a *InboundController) delInbound(c *gin.Context) {
|
|||||||
func (a *InboundController) updateInbound(c *gin.Context) {
|
func (a *InboundController) updateInbound(c *gin.Context) {
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.inbounds.revise"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inbound := &model.Inbound{
|
inbound := &model.Inbound{
|
||||||
@ -114,11 +113,11 @@ func (a *InboundController) updateInbound(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
err = c.ShouldBind(inbound)
|
err = c.ShouldBind(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.inbounds.revise"), err)
|
jsonMsg(c, I18n(c, "pages.inbounds.revise"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inbound, err = a.inboundService.UpdateInbound(inbound)
|
inbound, err = a.inboundService.UpdateInbound(inbound)
|
||||||
jsonMsgObj(c, I18n(c , "pages.inbounds.revise"), inbound, err)
|
jsonMsgObj(c, I18n(c, "pages.inbounds.revise"), inbound, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
a.xrayService.SetToNeedRestart()
|
a.xrayService.SetToNeedRestart()
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func (a *IndexController) login(c *gin.Context) {
|
|||||||
var form LoginForm
|
var form LoginForm
|
||||||
err := c.ShouldBind(&form)
|
err := c.ShouldBind(&form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pureJsonMsg(c, false, I18n(c , "pages.login.toasts.invalidFormData"))
|
pureJsonMsg(c, false, I18n(c, "pages.login.toasts.invalidFormData"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if form.Username == "" {
|
if form.Username == "" {
|
||||||
@ -54,7 +54,7 @@ func (a *IndexController) login(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if form.Password == "" {
|
if form.Password == "" {
|
||||||
pureJsonMsg(c, false, I18n(c , "pages.login.toasts.emptyPassword"))
|
pureJsonMsg(c, false, I18n(c, "pages.login.toasts.emptyPassword"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := a.userService.CheckUser(form.Username, form.Password)
|
user := a.userService.CheckUser(form.Username, form.Password)
|
||||||
@ -62,7 +62,7 @@ func (a *IndexController) login(c *gin.Context) {
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
job.NewStatsNotifyJob().UserLoginNotify(form.Username, getRemoteIp(c), timeStr, 0)
|
job.NewStatsNotifyJob().UserLoginNotify(form.Username, getRemoteIp(c), timeStr, 0)
|
||||||
logger.Infof("wrong username or password: \"%s\" \"%s\"", form.Username, form.Password)
|
logger.Infof("wrong username or password: \"%s\" \"%s\"", form.Username, form.Password)
|
||||||
pureJsonMsg(c, false, I18n(c , "pages.login.toasts.wrongUsernameOrPassword"))
|
pureJsonMsg(c, false, I18n(c, "pages.login.toasts.wrongUsernameOrPassword"))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
logger.Infof("%s login success,Ip Address:%s\n", form.Username, getRemoteIp(c))
|
logger.Infof("%s login success,Ip Address:%s\n", form.Username, getRemoteIp(c))
|
||||||
@ -71,7 +71,7 @@ func (a *IndexController) login(c *gin.Context) {
|
|||||||
|
|
||||||
err = session.SetLoginUser(c, user)
|
err = session.SetLoginUser(c, user)
|
||||||
logger.Info("user", user.Id, "login success")
|
logger.Info("user", user.Id, "login success")
|
||||||
jsonMsg(c, I18n(c , "pages.login.toasts.successLogin"), err)
|
jsonMsg(c, I18n(c, "pages.login.toasts.successLogin"), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *IndexController) logout(c *gin.Context) {
|
func (a *IndexController) logout(c *gin.Context) {
|
||||||
|
@ -68,7 +68,7 @@ func (a *ServerController) getXrayVersion(c *gin.Context) {
|
|||||||
|
|
||||||
versions, err := a.serverService.GetXrayVersions()
|
versions, err := a.serverService.GetXrayVersions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "getVersion"), err)
|
jsonMsg(c, I18n(c, "getVersion"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,5 +81,5 @@ func (a *ServerController) getXrayVersion(c *gin.Context) {
|
|||||||
func (a *ServerController) installXray(c *gin.Context) {
|
func (a *ServerController) installXray(c *gin.Context) {
|
||||||
version := c.Param("version")
|
version := c.Param("version")
|
||||||
err := a.serverService.UpdateXray(version)
|
err := a.serverService.UpdateXray(version)
|
||||||
jsonMsg(c, I18n(c , "install") + " xray", err)
|
jsonMsg(c, I18n(c, "install")+" xray", err)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (a *SettingController) initRouter(g *gin.RouterGroup) {
|
|||||||
func (a *SettingController) getAllSetting(c *gin.Context) {
|
func (a *SettingController) getAllSetting(c *gin.Context) {
|
||||||
allSetting, err := a.settingService.GetAllSetting()
|
allSetting, err := a.settingService.GetAllSetting()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.getSetting"), err)
|
jsonMsg(c, I18n(c, "pages.setting.toasts.getSetting"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonObj(c, allSetting, nil)
|
jsonObj(c, allSetting, nil)
|
||||||
@ -50,27 +50,27 @@ func (a *SettingController) updateSetting(c *gin.Context) {
|
|||||||
allSetting := &entity.AllSetting{}
|
allSetting := &entity.AllSetting{}
|
||||||
err := c.ShouldBind(allSetting)
|
err := c.ShouldBind(allSetting)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.modifySetting"), err)
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifySetting"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = a.settingService.UpdateAllSetting(allSetting)
|
err = a.settingService.UpdateAllSetting(allSetting)
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.modifySetting"), err)
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifySetting"), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SettingController) updateUser(c *gin.Context) {
|
func (a *SettingController) updateUser(c *gin.Context) {
|
||||||
form := &updateUserForm{}
|
form := &updateUserForm{}
|
||||||
err := c.ShouldBind(form)
|
err := c.ShouldBind(form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.modifySetting"), err)
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifySetting"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := session.GetLoginUser(c)
|
user := session.GetLoginUser(c)
|
||||||
if user.Username != form.OldUsername || user.Password != form.OldPassword {
|
if user.Username != form.OldUsername || user.Password != form.OldPassword {
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.modifyUser"), errors.New(I18n(c , "pages.setting.toasts.originalUserPassIncorrect")))
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifyUser"), errors.New(I18n(c, "pages.setting.toasts.originalUserPassIncorrect")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if form.NewUsername == "" || form.NewPassword == "" {
|
if form.NewUsername == "" || form.NewPassword == "" {
|
||||||
jsonMsg(c,I18n(c , "pages.setting.toasts.modifyUser"), errors.New(I18n(c , "pages.setting.toasts.userPassMustBeNotEmpty")))
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifyUser"), errors.New(I18n(c, "pages.setting.toasts.userPassMustBeNotEmpty")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = a.userService.UpdateUser(user.Id, form.NewUsername, form.NewPassword)
|
err = a.userService.UpdateUser(user.Id, form.NewUsername, form.NewPassword)
|
||||||
@ -79,10 +79,10 @@ func (a *SettingController) updateUser(c *gin.Context) {
|
|||||||
user.Password = form.NewPassword
|
user.Password = form.NewPassword
|
||||||
session.SetLoginUser(c, user)
|
session.SetLoginUser(c, user)
|
||||||
}
|
}
|
||||||
jsonMsg(c, I18n(c , "pages.setting.toasts.modifyUser"), err)
|
jsonMsg(c, I18n(c, "pages.setting.toasts.modifyUser"), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SettingController) restartPanel(c *gin.Context) {
|
func (a *SettingController) restartPanel(c *gin.Context) {
|
||||||
err := a.panelService.RestartPanel(time.Second * 3)
|
err := a.panelService.RestartPanel(time.Second * 3)
|
||||||
jsonMsg(c, I18n(c , "pages.setting.restartPanel"), err)
|
jsonMsg(c, I18n(c, "pages.setting.restartPanel"), err)
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,12 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
m.Success = true
|
m.Success = true
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
m.Msg = msg + I18n(c , "success")
|
m.Msg = msg + I18n(c, "success")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m.Success = false
|
m.Success = false
|
||||||
m.Msg = msg + I18n(c , "fail") + ": " + err.Error()
|
m.Msg = msg + I18n(c, "fail") + ": " + err.Error()
|
||||||
logger.Warning(msg + I18n(c , "fail") + ": ", err)
|
logger.Warning(msg+I18n(c, "fail")+": ", err)
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, m)
|
c.JSON(http.StatusOK, m)
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
Username
|
Email
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
The Username Must Be Completely Unique
|
The Email Must Be Completely Unique
|
||||||
</template>
|
</template>
|
||||||
<!--Renew Svg Icon-->
|
<!--Renew Svg Icon-->
|
||||||
<svg
|
<svg
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
Username
|
Email
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
The Username Must Be Completely Unique
|
The Email Must Be Completely Unique
|
||||||
</template>
|
</template>
|
||||||
<!--Renew Svg Icon-->
|
<!--Renew Svg Icon-->
|
||||||
<svg
|
<svg
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
Username
|
Email
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
The Username Must Be Completely Unique
|
The Email Must Be Completely Unique
|
||||||
</template>
|
</template>
|
||||||
<!--Renew Svg Icon-->
|
<!--Renew Svg Icon-->
|
||||||
<svg
|
<svg
|
||||||
|
@ -152,13 +152,18 @@
|
|||||||
const columns = [{
|
const columns = [{
|
||||||
title: '{{ i18n "pages.inbounds.operate" }}',
|
title: '{{ i18n "pages.inbounds.operate" }}',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 40,
|
width: 50,
|
||||||
scopedSlots: { customRender: 'action' },
|
scopedSlots: { customRender: 'action' },
|
||||||
}, {
|
}, {
|
||||||
title: '{{ i18n "pages.inbounds.enable" }}',
|
title: '{{ i18n "pages.inbounds.enable" }}',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 40,
|
width: 40,
|
||||||
scopedSlots: { customRender: 'enable' },
|
scopedSlots: { customRender: 'enable' },
|
||||||
|
}, {
|
||||||
|
title: "Id",
|
||||||
|
align: 'center',
|
||||||
|
dataIndex: "id",
|
||||||
|
width: 20,
|
||||||
}, {
|
}, {
|
||||||
title: '{{ i18n "pages.inbounds.remark" }}',
|
title: '{{ i18n "pages.inbounds.remark" }}',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@ -192,8 +197,8 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
const innerColumns = [
|
const innerColumns = [
|
||||||
{ title: '', width: 20, scopedSlots: { customRender: 'actions' } },
|
{ title: '', width: 70, scopedSlots: { customRender: 'actions' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
|
{ title: '{{ i18n "pages.inbounds.client" }}', width: 60, scopedSlots: { customRender: 'client' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 80, scopedSlots: { customRender: 'traffic' } },
|
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 80, scopedSlots: { customRender: 'traffic' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
|
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
|
||||||
{ title: 'UID', width: 150, dataIndex: "id" },
|
{ title: 'UID', width: 150, dataIndex: "id" },
|
||||||
@ -201,15 +206,15 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
const innerTrojanColumns = [
|
const innerTrojanColumns = [
|
||||||
{ title: '', width: 20, scopedSlots: { customRender: 'actions' } },
|
{ title: '', width: 70, scopedSlots: { customRender: 'actions' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.client" }}', width: 80, scopedSlots: { customRender: 'client' } },
|
{ title: '{{ i18n "pages.inbounds.client" }}', width: 60, scopedSlots: { customRender: 'client' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 80, scopedSlots: { customRender: 'traffic' } },
|
{ title: '{{ i18n "pages.inbounds.traffic" }}↑|↓', width: 80, scopedSlots: { customRender: 'traffic' } },
|
||||||
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
|
{ title: '{{ i18n "pages.inbounds.expireDate" }}', width: 70, scopedSlots: { customRender: 'expiryTime' } },
|
||||||
{ title: 'Password', width: 150, dataIndex: "password" },
|
{ title: 'Password', width: 150, dataIndex: "password" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const innerOneColumns = [
|
const innerOneColumns = [
|
||||||
{ title: '', width: 50, scopedSlots: { customRender: 'actions' } },
|
{ title: '', width: 70, scopedSlots: { customRender: 'actions' } },
|
||||||
];
|
];
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
@ -276,7 +281,7 @@
|
|||||||
this.showQrcode(dbInbound);
|
this.showQrcode(dbInbound);
|
||||||
break;
|
break;
|
||||||
case "edit":
|
case "edit":
|
||||||
this.openEditInbound(dbInbound);
|
this.openEditInbound(dbInbound.id);
|
||||||
break;
|
break;
|
||||||
case "resetTraffic":
|
case "resetTraffic":
|
||||||
this.resetTraffic(dbInbound);
|
this.resetTraffic(dbInbound);
|
||||||
@ -299,7 +304,8 @@
|
|||||||
isEdit: false
|
isEdit: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openEditInbound(dbInbound) {
|
openEditInbound(dbInbound_id) {
|
||||||
|
dbInbound = this.dbInbounds.find(row => row.id === dbInbound_id);
|
||||||
const inbound = dbInbound.toInbound();
|
const inbound = dbInbound.toInbound();
|
||||||
inModal.show({
|
inModal.show({
|
||||||
title: '{{ i18n "pages.inbounds.modifyInbound"}}',
|
title: '{{ i18n "pages.inbounds.modifyInbound"}}',
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
{{define "client_row"}}
|
{{define "client_row"}}
|
||||||
<template slot="actions" slot-scope="text, client, index">
|
<template slot="actions" slot-scope="text, client, index">
|
||||||
<a-dropdown>
|
<a-icon v-if="record.hasLink()" style="font-size: 26px" type="qrcode" @click="showQrcode(record,index);"></a-icon>
|
||||||
<a-icon @click="e => e.preventDefault()" type="menu"></a-icon>
|
<a-icon v-if="client.email != ''" style="font-size: 26px" type="retweet" @click="resetClientTraffic(client,record,$event)"></a-icon>
|
||||||
<template #overlay>
|
<a-icon type="info-circle" style="font-size: 26px" @click="showInfo(record,index);"></a-icon>
|
||||||
<a-menu>
|
|
||||||
<a-menu-item v-if="record.hasLink()" @click="showQrcode(record,index);"><a-icon type="qrcode"></a-icon>{{ i18n "qrCode" }}</a-menu-item>
|
|
||||||
<a-menu-item @click="showInfo(record,index);"><a-icon type="info-circle"></a-icon>{{ i18n "info" }}</a-menu-item>
|
|
||||||
<a-menu-item @click="resetClientTraffic(client,record,$event)" v-if="client.email != ''"><a-icon type="retweet"></a-icon>{{ i18n "pages.inbounds.resetTraffic" }}</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</template>
|
</template>
|
||||||
<template slot="client" slot-scope="text, client">
|
<template slot="client" slot-scope="text, client">
|
||||||
[[ client.email ]]
|
[[ client.email ]]
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/util/common"
|
"x-ui/util/common"
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ func (j *StatsNotifyJob) SendMsgToTgbot(msg string) {
|
|||||||
bot.Send(info)
|
bot.Send(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Here run is a interface method of Job interface
|
// Here run is a interface method of Job interface
|
||||||
func (j *StatsNotifyJob) Run() {
|
func (j *StatsNotifyJob) Run() {
|
||||||
if !j.xrayService.IsXrayRunning() {
|
if !j.xrayService.IsXrayRunning() {
|
||||||
return
|
return
|
||||||
@ -94,14 +95,14 @@ func (j *StatsNotifyJob) Run() {
|
|||||||
}
|
}
|
||||||
info += fmt.Sprintf("IP:%s\r\n \r\n", ip)
|
info += fmt.Sprintf("IP:%s\r\n \r\n", ip)
|
||||||
|
|
||||||
//get traffic
|
// get traffic
|
||||||
inbouds, err := j.inboundService.GetAllInbounds()
|
inbouds, err := j.inboundService.GetAllInbounds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("StatsNotifyJob run failed:", err)
|
logger.Warning("StatsNotifyJob run failed:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//NOTE:If there no any sessions here,need to notify here
|
// NOTE:If there no any sessions here,need to notify here
|
||||||
//TODO:分节点推送,自动转化格式
|
// TODO:Sub-node push, automatic conversion format
|
||||||
for _, inbound := range inbouds {
|
for _, inbound := range inbouds {
|
||||||
info += fmt.Sprintf("Node name:%s\r\nPort:%d\r\nUpload↑:%s\r\nDownload↓:%s\r\nTotal:%s\r\n", inbound.Remark, inbound.Port, common.FormatTraffic(inbound.Up), common.FormatTraffic(inbound.Down), common.FormatTraffic((inbound.Up + inbound.Down)))
|
info += fmt.Sprintf("Node name:%s\r\nPort:%d\r\nUpload↑:%s\r\nDownload↓:%s\r\nTotal:%s\r\n", inbound.Remark, inbound.Port, common.FormatTraffic(inbound.Up), common.FormatTraffic(inbound.Down), common.FormatTraffic((inbound.Up + inbound.Down)))
|
||||||
if inbound.ExpiryTime == 0 {
|
if inbound.ExpiryTime == 0 {
|
||||||
@ -119,7 +120,7 @@ func (j *StatsNotifyJob) UserLoginNotify(username string, ip string, time string
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var msg string
|
var msg string
|
||||||
//get hostname
|
// Get hostname
|
||||||
name, err := os.Hostname()
|
name, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("get hostname error:", err)
|
fmt.Println("get hostname error:", err)
|
||||||
@ -136,11 +137,10 @@ func (j *StatsNotifyJob) UserLoginNotify(username string, ip string, time string
|
|||||||
j.SendMsgToTgbot(msg)
|
j.SendMsgToTgbot(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var numericKeyboard = tgbotapi.NewInlineKeyboardMarkup(
|
var numericKeyboard = tgbotapi.NewInlineKeyboardMarkup(
|
||||||
tgbotapi.NewInlineKeyboardRow(
|
tgbotapi.NewInlineKeyboardRow(
|
||||||
tgbotapi.NewInlineKeyboardButtonData("Get Usage", "get_usage"),
|
tgbotapi.NewInlineKeyboardButtonData("Get Usage", "get_usage"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
func (j *StatsNotifyJob) OnReceive() *StatsNotifyJob {
|
func (j *StatsNotifyJob) OnReceive() *StatsNotifyJob {
|
||||||
@ -156,13 +156,13 @@ func (j *StatsNotifyJob) OnReceive() *StatsNotifyJob {
|
|||||||
}
|
}
|
||||||
bot.Debug = false
|
bot.Debug = false
|
||||||
u := tgbotapi.NewUpdate(0)
|
u := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 10
|
u.Timeout = 10
|
||||||
|
|
||||||
updates := bot.GetUpdatesChan(u)
|
updates := bot.GetUpdatesChan(u)
|
||||||
|
|
||||||
|
for update := range updates {
|
||||||
|
if update.Message == nil {
|
||||||
|
|
||||||
for update := range updates {
|
|
||||||
if update.Message == nil {
|
|
||||||
|
|
||||||
if update.CallbackQuery != nil {
|
if update.CallbackQuery != nil {
|
||||||
// Respond to the callback query, telling Telegram to show the user
|
// Respond to the callback query, telling Telegram to show the user
|
||||||
// a message with the data received.
|
// a message with the data received.
|
||||||
@ -170,60 +170,60 @@ func (j *StatsNotifyJob) OnReceive() *StatsNotifyJob {
|
|||||||
if _, err := bot.Request(callback); err != nil {
|
if _, err := bot.Request(callback); err != nil {
|
||||||
logger.Warning(err)
|
logger.Warning(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// And finally, send a message containing the data received.
|
// And finally, send a message containing the data received.
|
||||||
msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, "")
|
msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, "")
|
||||||
|
|
||||||
switch update.CallbackQuery.Data {
|
switch update.CallbackQuery.Data {
|
||||||
case "get_usage":
|
case "get_usage":
|
||||||
msg.Text = "for get your usage send command like this : \n <code>/usage uuid | id</code> \n example : <code>/usage fc3239ed-8f3b-4151-ff51-b183d5182142</code>"
|
msg.Text = "for get your usage send command like this : \n <code>/usage uuid | id</code> \n example : <code>/usage fc3239ed-8f3b-4151-ff51-b183d5182142</code>"
|
||||||
msg.ParseMode = "HTML"
|
msg.ParseMode = "HTML"
|
||||||
}
|
}
|
||||||
if _, err := bot.Send(msg); err != nil {
|
if _, err := bot.Send(msg); err != nil {
|
||||||
logger.Warning(err)
|
logger.Warning(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !update.Message.IsCommand() { // ignore any non-command Messages
|
continue
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new MessageConfig. We don't have text yet,
|
if !update.Message.IsCommand() { // ignore any non-command Messages
|
||||||
// so we leave it empty.
|
continue
|
||||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
|
}
|
||||||
|
|
||||||
// Extract the command from the Message.
|
// Create a new MessageConfig. We don't have text yet,
|
||||||
switch update.Message.Command() {
|
// so we leave it empty.
|
||||||
case "help":
|
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
|
||||||
msg.Text = "What you need?"
|
|
||||||
|
// Extract the command from the Message.
|
||||||
|
switch update.Message.Command() {
|
||||||
|
case "help":
|
||||||
|
msg.Text = "What you need?"
|
||||||
msg.ReplyMarkup = numericKeyboard
|
msg.ReplyMarkup = numericKeyboard
|
||||||
case "start":
|
case "start":
|
||||||
msg.Text = "Hi :) \n What you need?"
|
msg.Text = "Hi :) \n What you need?"
|
||||||
msg.ReplyMarkup = numericKeyboard
|
msg.ReplyMarkup = numericKeyboard
|
||||||
|
|
||||||
case "status":
|
case "status":
|
||||||
msg.Text = "bot is ok."
|
msg.Text = "bot is ok."
|
||||||
|
|
||||||
case "usage":
|
case "usage":
|
||||||
msg.Text = j.getClientUsage(update.Message.CommandArguments())
|
msg.Text = j.getClientUsage(update.Message.CommandArguments())
|
||||||
default:
|
default:
|
||||||
msg.Text = "I don't know that command, /help"
|
msg.Text = "I don't know that command, /help"
|
||||||
msg.ReplyMarkup = numericKeyboard
|
msg.ReplyMarkup = numericKeyboard
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := bot.Send(msg); err != nil {
|
if _, err := bot.Send(msg); err != nil {
|
||||||
logger.Warning(err)
|
logger.Warning(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return j
|
return j
|
||||||
|
|
||||||
}
|
}
|
||||||
func (j *StatsNotifyJob) getClientUsage(id string) string {
|
func (j *StatsNotifyJob) getClientUsage(id string) string {
|
||||||
traffic , err := j.inboundService.GetClientTrafficById(id)
|
traffic, err := j.inboundService.GetClientTrafficById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(err)
|
logger.Warning(err)
|
||||||
return "something wrong!"
|
return "something wrong!"
|
||||||
@ -241,8 +241,8 @@ func (j *StatsNotifyJob) getClientUsage(id string) string {
|
|||||||
total = fmt.Sprintf("%s", common.FormatTraffic((traffic.Total)))
|
total = fmt.Sprintf("%s", common.FormatTraffic((traffic.Total)))
|
||||||
}
|
}
|
||||||
output := fmt.Sprintf("💡 Active: %t\r\n📧 Email: %s\r\n🔼 Upload↑: %s\r\n🔽 Download↓: %s\r\n🔄 Total: %s / %s\r\n📅 Expire in: %s\r\n",
|
output := fmt.Sprintf("💡 Active: %t\r\n📧 Email: %s\r\n🔼 Upload↑: %s\r\n🔽 Download↓: %s\r\n🔄 Total: %s / %s\r\n📅 Expire in: %s\r\n",
|
||||||
traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)),
|
traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)),
|
||||||
total, expiryTime)
|
total, expiryTime)
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
"x-ui/database"
|
"x-ui/database"
|
||||||
"encoding/json"
|
|
||||||
"x-ui/database/model"
|
"x-ui/database/model"
|
||||||
|
"x-ui/logger"
|
||||||
"x-ui/util/common"
|
"x-ui/util/common"
|
||||||
"x-ui/xray"
|
"x-ui/xray"
|
||||||
"x-ui/logger"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -64,11 +64,11 @@ func (s *InboundService) getClients(inbound *model.Inbound) ([]model.Client, err
|
|||||||
return clients, nil
|
return clients, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) checkEmailsExist(emails map[string] bool, ignoreId int) (string, error) {
|
func (s *InboundService) checkEmailsExist(emails map[string]bool, ignoreId int) (string, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
var inbounds []*model.Inbound
|
var inbounds []*model.Inbound
|
||||||
db = db.Model(model.Inbound{}).Where("Protocol in ?", []model.Protocol{model.VMess, model.VLESS})
|
db = db.Model(model.Inbound{}).Where("Protocol in ?", []model.Protocol{model.VMess, model.VLESS, model.Trojan})
|
||||||
if (ignoreId > 0) {
|
if ignoreId > 0 {
|
||||||
db = db.Where("id != ?", ignoreId)
|
db = db.Where("id != ?", ignoreId)
|
||||||
}
|
}
|
||||||
db = db.Find(&inbounds)
|
db = db.Find(&inbounds)
|
||||||
@ -96,25 +96,25 @@ func (s *InboundService) checkEmailExistForInbound(inbound *model.Inbound) (stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
emails := make(map[string] bool)
|
emails := make(map[string]bool)
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if (client.Email != "") {
|
if client.Email != "" {
|
||||||
if emails[client.Email] {
|
if emails[client.Email] {
|
||||||
return client.Email, nil
|
return client.Email, nil
|
||||||
}
|
}
|
||||||
emails[client.Email] = true;
|
emails[client.Email] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.checkEmailsExist(emails, inbound.Id)
|
return s.checkEmailsExist(emails, inbound.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound,error) {
|
func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, error) {
|
||||||
exist, err := s.checkPortExist(inbound.Port, 0)
|
exist, err := s.checkPortExist(inbound.Port, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return inbound, err
|
return inbound, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
return inbound, common.NewError("端口已存在:", inbound.Port)
|
return inbound, common.NewError("Port already exists:", inbound.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
existEmail, err := s.checkEmailExistForInbound(inbound)
|
existEmail, err := s.checkEmailExistForInbound(inbound)
|
||||||
@ -129,7 +129,7 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound,erro
|
|||||||
|
|
||||||
err = db.Save(inbound).Error
|
err = db.Save(inbound).Error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.UpdateClientStat(inbound.Id,inbound.Settings)
|
s.UpdateClientStat(inbound.Id, inbound.Settings)
|
||||||
}
|
}
|
||||||
return inbound, err
|
return inbound, err
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func (s *InboundService) AddInbounds(inbounds []*model.Inbound) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
return common.NewError("端口已存在:", inbound.Port)
|
return common.NewError("Port already exists:", inbound.Port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,9 +187,9 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
|
|||||||
return inbound, err
|
return inbound, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
return inbound, common.NewError("端口已存在:", inbound.Port)
|
return inbound, common.NewError("Port already exists:", inbound.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
existEmail, err := s.checkEmailExistForInbound(inbound)
|
existEmail, err := s.checkEmailExistForInbound(inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return inbound, err
|
return inbound, err
|
||||||
@ -216,7 +216,7 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
|
|||||||
oldInbound.Sniffing = inbound.Sniffing
|
oldInbound.Sniffing = inbound.Sniffing
|
||||||
oldInbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
oldInbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
|
||||||
|
|
||||||
s.UpdateClientStat(inbound.Id,inbound.Settings)
|
s.UpdateClientStat(inbound.Id, inbound.Settings)
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
return inbound, db.Save(oldInbound).Error
|
return inbound, db.Save(oldInbound).Error
|
||||||
}
|
}
|
||||||
@ -276,13 +276,13 @@ func (s *InboundService) AddClientTraffic(traffics []*xray.ClientTraffic) (err e
|
|||||||
for _, traffic := range traffics {
|
for _, traffic := range traffics {
|
||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
|
|
||||||
err := txInbound.Where("settings like ?", "%" + traffic.Email + "%").First(inbound).Error
|
err := txInbound.Where("settings like ?", "%"+traffic.Email+"%").First(inbound).Error
|
||||||
traffic.InboundId = inbound.Id
|
traffic.InboundId = inbound.Id
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
// delete removed client record
|
// delete removed client record
|
||||||
clientErr := s.DelClientStat(tx, traffic.Email)
|
clientErr := s.DelClientStat(tx, traffic.Email)
|
||||||
logger.Warning(err, traffic.Email,clientErr)
|
logger.Warning(err, traffic.Email, clientErr)
|
||||||
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -298,19 +298,19 @@ func (s *InboundService) AddClientTraffic(traffics []*xray.ClientTraffic) (err e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tx.Where("inbound_id = ?", inbound.Id).Where("email = ?", traffic.Email).
|
if tx.Where("inbound_id = ?", inbound.Id).Where("email = ?", traffic.Email).
|
||||||
UpdateColumn("enable", true).
|
UpdateColumn("enable", true).
|
||||||
UpdateColumn("expiry_time", traffic.ExpiryTime).
|
UpdateColumn("expiry_time", traffic.ExpiryTime).
|
||||||
UpdateColumn("total",traffic.Total).
|
UpdateColumn("total", traffic.Total).
|
||||||
UpdateColumn("up", gorm.Expr("up + ?", traffic.Up)).
|
UpdateColumn("up", gorm.Expr("up + ?", traffic.Up)).
|
||||||
UpdateColumn("down", gorm.Expr("down + ?", traffic.Down)).RowsAffected == 0 {
|
UpdateColumn("down", gorm.Expr("down + ?", traffic.Down)).RowsAffected == 0 {
|
||||||
err = tx.Create(traffic).Error
|
err = tx.Create(traffic).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("AddClientTraffic update data ", err)
|
logger.Warning("AddClientTraffic update data ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ func (s *InboundService) DisableInvalidClients() (int64, error) {
|
|||||||
count := result.RowsAffected
|
count := result.RowsAffected
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
func (s *InboundService) UpdateClientStat(inboundId int, inboundSettings string) (error) {
|
func (s *InboundService) UpdateClientStat(inboundId int, inboundSettings string) error {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
// get settings clients
|
// get settings clients
|
||||||
@ -344,8 +344,8 @@ func (s *InboundService) UpdateClientStat(inboundId int, inboundSettings string)
|
|||||||
clients := settings["clients"]
|
clients := settings["clients"]
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
result := db.Model(xray.ClientTraffic{}).
|
result := db.Model(xray.ClientTraffic{}).
|
||||||
Where("inbound_id = ? and email = ?", inboundId, client.Email).
|
Where("inbound_id = ? and email = ?", inboundId, client.Email).
|
||||||
Updates(map[string]interface{}{"enable": true, "total": client.TotalGB, "expiry_time": client.ExpiryTime})
|
Updates(map[string]interface{}{"enable": true, "total": client.TotalGB, "expiry_time": client.ExpiryTime})
|
||||||
if result.RowsAffected == 0 {
|
if result.RowsAffected == 0 {
|
||||||
clientTraffic := xray.ClientTraffic{}
|
clientTraffic := xray.ClientTraffic{}
|
||||||
clientTraffic.InboundId = inboundId
|
clientTraffic.InboundId = inboundId
|
||||||
@ -361,7 +361,7 @@ func (s *InboundService) UpdateClientStat(inboundId int, inboundSettings string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ func (s *InboundService) DelClientStat(tx *gorm.DB, email string) error {
|
|||||||
return tx.Where("email = ?", email).Delete(xray.ClientTraffic{}).Error
|
return tx.Where("email = ?", email).Delete(xray.ClientTraffic{}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) ResetClientTraffic(clientEmail string) (error) {
|
func (s *InboundService) ResetClientTraffic(clientEmail string) error {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
result := db.Model(xray.ClientTraffic{}).
|
result := db.Model(xray.ClientTraffic{}).
|
||||||
@ -379,7 +379,6 @@ func (s *InboundService) ResetClientTraffic(clientEmail string) (error) {
|
|||||||
|
|
||||||
err := result.Error
|
err := result.Error
|
||||||
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -390,7 +389,7 @@ func (s *InboundService) GetClientTrafficById(uuid string) (traffic *xray.Client
|
|||||||
inbound := &model.Inbound{}
|
inbound := &model.Inbound{}
|
||||||
traffic = &xray.ClientTraffic{}
|
traffic = &xray.ClientTraffic{}
|
||||||
|
|
||||||
err = db.Model(model.Inbound{}).Where("settings like ?", "%" + uuid + "%").First(inbound).Error
|
err = db.Model(model.Inbound{}).Where("settings like ?", "%"+uuid+"%").First(inbound).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
logger.Warning(err)
|
logger.Warning(err)
|
||||||
|
@ -69,7 +69,7 @@ func (s *SettingService) GetAllSetting() (*entity.AllSetting, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
// 有些设置自动生成,不需要返回到前端给用户修改
|
// Some settings are automatically generated, no need to return to the front end to modify the user
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/xray"
|
"x-ui/xray"
|
||||||
|
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ func (s *XrayService) GetXrayVersion() string {
|
|||||||
}
|
}
|
||||||
return p.GetVersion()
|
return p.GetVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveIndex(s []interface{}, index int) []interface{} {
|
func RemoveIndex(s []interface{}, index int) []interface{} {
|
||||||
return append(s[:index], s[index+1:]...)
|
return append(s[:index], s[index+1:]...)
|
||||||
}
|
}
|
||||||
@ -79,25 +81,24 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
|||||||
// get settings clients
|
// get settings clients
|
||||||
settings := map[string]interface{}{}
|
settings := map[string]interface{}{}
|
||||||
json.Unmarshal([]byte(inbound.Settings), &settings)
|
json.Unmarshal([]byte(inbound.Settings), &settings)
|
||||||
clients, ok := settings["clients"].([]interface{})
|
clients, ok := settings["clients"].([]interface{})
|
||||||
if ok {
|
if ok {
|
||||||
// check users active or not
|
// check users active or not
|
||||||
|
|
||||||
clientStats := inbound.ClientStats
|
clientStats := inbound.ClientStats
|
||||||
for _, clientTraffic := range clientStats {
|
for _, clientTraffic := range clientStats {
|
||||||
|
|
||||||
for index, client := range clients {
|
for index, client := range clients {
|
||||||
c := client.(map[string]interface{})
|
c := client.(map[string]interface{})
|
||||||
if c["email"] == clientTraffic.Email {
|
if c["email"] == clientTraffic.Email {
|
||||||
if ! clientTraffic.Enable {
|
if !clientTraffic.Enable {
|
||||||
clients = RemoveIndex(clients,index)
|
clients = RemoveIndex(clients, index)
|
||||||
logger.Info("Remove Inbound User",c["email"] ,"due the expire or traffic limit")
|
logger.Info("Remove Inbound User", c["email"], "due the expire or traffic limit")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
settings["clients"] = clients
|
settings["clients"] = clients
|
||||||
@ -105,7 +106,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
inbound.Settings = string(modifiedSettings)
|
inbound.Settings = string(modifiedSettings)
|
||||||
}
|
}
|
||||||
inboundConfig := inbound.GenXrayInboundConfig()
|
inboundConfig := inbound.GenXrayInboundConfig()
|
||||||
|
18
web/web.go
18
web/web.go
@ -21,7 +21,7 @@ import (
|
|||||||
"x-ui/web/network"
|
"x-ui/web/network"
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/pelletier/go-toml/v2"
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-contrib/sessions/cookie"
|
"github.com/gin-contrib/sessions/cookie"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -271,7 +271,7 @@ func (s *Server) initI18n(engine *gin.Engine) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.FuncMap["i18n"] = I18n;
|
engine.FuncMap["i18n"] = I18n
|
||||||
|
|
||||||
engine.Use(func(c *gin.Context) {
|
engine.Use(func(c *gin.Context) {
|
||||||
//accept := c.GetHeader("Accept-Language")
|
//accept := c.GetHeader("Accept-Language")
|
||||||
@ -286,7 +286,7 @@ func (s *Server) initI18n(engine *gin.Engine) error {
|
|||||||
|
|
||||||
localizer = i18n.NewLocalizer(bundle, lang)
|
localizer = i18n.NewLocalizer(bundle, lang)
|
||||||
c.Set("localizer", localizer)
|
c.Set("localizer", localizer)
|
||||||
c.Set("I18n" , I18n)
|
c.Set("I18n", I18n)
|
||||||
c.Next()
|
c.Next()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -298,19 +298,19 @@ func (s *Server) startTask() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("start xray failed:", err)
|
logger.Warning("start xray failed:", err)
|
||||||
}
|
}
|
||||||
// 每 30 秒检查一次 xray 是否在运行
|
// Check whether xray is running every 30 seconds
|
||||||
s.cron.AddJob("@every 30s", job.NewCheckXrayRunningJob())
|
s.cron.AddJob("@every 30s", job.NewCheckXrayRunningJob())
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
// 每 10 秒统计一次流量,首次启动延迟 5 秒,与重启 xray 的时间错开
|
// Statistics every 10 seconds, start the delay for 5 seconds for the first time, and staggered with the time to restart xray
|
||||||
s.cron.AddJob("@every 10s", job.NewXrayTrafficJob())
|
s.cron.AddJob("@every 10s", job.NewXrayTrafficJob())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// 每 30 秒检查一次 inbound 流量超出和到期的情况
|
// Check the inbound traffic every 30 seconds that the traffic exceeds and expires
|
||||||
s.cron.AddJob("@every 30s", job.NewCheckInboundJob())
|
s.cron.AddJob("@every 30s", job.NewCheckInboundJob())
|
||||||
|
|
||||||
// 每一天提示一次流量情况,上海时间8点30
|
// Make a traffic condition every day, 8:30
|
||||||
var entry cron.EntryID
|
var entry cron.EntryID
|
||||||
isTgbotenabled, err := s.settingService.GetTgbotenabled()
|
isTgbotenabled, err := s.settingService.GetTgbotenabled()
|
||||||
if (err == nil) && (isTgbotenabled) {
|
if (err == nil) && (isTgbotenabled) {
|
||||||
@ -320,7 +320,7 @@ func (s *Server) startTask() {
|
|||||||
runtime = "@daily"
|
runtime = "@daily"
|
||||||
}
|
}
|
||||||
logger.Infof("Tg notify enabled,run at %s", runtime)
|
logger.Infof("Tg notify enabled,run at %s", runtime)
|
||||||
entry, err = s.cron.AddJob(runtime, job.NewStatsNotifyJob())
|
_, err = s.cron.AddJob(runtime, job.NewStatsNotifyJob())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Add NewStatsNotifyJob error", err)
|
logger.Warning("Add NewStatsNotifyJob error", err)
|
||||||
return
|
return
|
||||||
@ -333,7 +333,7 @@ func (s *Server) startTask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Start() (err error) {
|
func (s *Server) Start() (err error) {
|
||||||
//这是一个匿名函数,没没有函数名
|
//This is an anonymous function, no function name
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Stop()
|
s.Stop()
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package xray
|
package xray
|
||||||
|
|
||||||
type ClientTraffic struct {
|
type ClientTraffic struct {
|
||||||
Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
|
Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
|
||||||
InboundId int `json:"inboundId" form:"inboundId"`
|
InboundId int `json:"inboundId" form:"inboundId"`
|
||||||
Enable bool `json:"enable" form:"enable"`
|
Enable bool `json:"enable" form:"enable"`
|
||||||
Email string `json:"email" form:"email" gorm:"unique"`
|
Email string `json:"email" form:"email" gorm:"unique"`
|
||||||
Up int64 `json:"up" form:"up"`
|
Up int64 `json:"up" form:"up"`
|
||||||
Down int64 `json:"down" form:"down"`
|
Down int64 `json:"down" form:"down"`
|
||||||
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
ExpiryTime int64 `json:"expiryTime" form:"expiryTime"`
|
||||||
Total int64 `json:"total" form:"total"`
|
Total int64 `json:"total" form:"total"`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user