From b6f84af6bd074ca2b916ad9ddb685ce6a6f9adda Mon Sep 17 00:00:00 2001 From: royalcat Date: Thu, 10 Oct 2024 16:02:38 +0300 Subject: [PATCH] init --- go.mod | 7 ++ go.sum | 4 + main.go | 5 ++ src/panels/3x/api.go | 181 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 src/panels/3x/api.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8d912d5 --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module vpn.konfach.ru/controller + +go 1.23.2 + +require github.com/carlmjohnson/requests v0.24.2 + +require golang.org/x/net v0.27.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b94eb8f --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/carlmjohnson/requests v0.24.2 h1:JDakhAmTIKL/qL/1P7Kkc2INGBJIkIFP6xUeUmPzLso= +github.com/carlmjohnson/requests v0.24.2/go.mod h1:duYA/jDnyZ6f3xbcF5PpZ9N8clgopubP2nK5i6MVMhU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= diff --git a/main.go b/main.go new file mode 100644 index 0000000..7905807 --- /dev/null +++ b/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/src/panels/3x/api.go b/src/panels/3x/api.go new file mode 100644 index 0000000..a3a83c0 --- /dev/null +++ b/src/panels/3x/api.go @@ -0,0 +1,181 @@ +package tresx + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/cookiejar" + "net/url" + + "github.com/carlmjohnson/requests" +) + +type XUIPriovider struct { + baseUrl string + client *http.Client +} + +func NewTresXProvider(basePath string) *XUIPriovider { + jar, err := cookiejar.New(nil) + if err != nil { + panic(err) + } + + return &XUIPriovider{ + baseUrl: basePath, + client: &http.Client{ + Jar: jar, + }, + } +} + +type basicResponse struct { + Success bool `json:"success"` + Message string `json:"msg"` + Object json.RawMessage `json:"obj"` +} + +func (t *XUIPriovider) Login(login, password string) error { + params := url.Values{} + params.Add("username", login) + params.Add("password", password) + + url := fmt.Sprintf("%s/login?%s", t.baseUrl, params.Encode()) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return err + } + res, err := t.client.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return err + } + var resp basicResponse + err = json.Unmarshal(body, &resp) + if err != nil { + return err + } + + if !resp.Success { + return fmt.Errorf("login failed: %s", resp.Message) + } + + return nil +} + +type Inbound struct { + ID int64 `json:"id"` + Up int64 `json:"up"` + Down int64 `json:"down"` + Total int64 `json:"total"` + Remark string `json:"remark"` + Enable bool `json:"enable"` + ExpiryTime int64 `json:"expiryTime"` + ClientStats []ClientStat `json:"clientStats"` + Listen string `json:"listen"` + Port int64 `json:"port"` + Protocol string `json:"protocol"` + Settings string `json:"settings"` + StreamSettings string `json:"streamSettings"` + Tag string `json:"tag"` + Sniffing string `json:"sniffing"` + Allocate string `json:"allocate"` +} + +type ClientStat struct { + ID int64 `json:"id"` + InboundID int64 `json:"inboundId"` + Enable bool `json:"enable"` + Email string `json:"email"` + Up int64 `json:"up"` + Down int64 `json:"down"` + ExpiryTime int64 `json:"expiryTime"` + Total int64 `json:"total"` + Reset int64 `json:"reset"` +} + +func (t *XUIPriovider) Inbounds(ctx context.Context) error { + var resp basicResponse + err := requests. + URL(t.baseUrl). + Path("panel/api/inbounds/list"). + Client(t.client). + ToJSON(&resp). + Fetch(ctx) + if err != nil { + return err + } + + if !resp.Success { + return fmt.Errorf("logout failed: %s", resp.Message) + } + + var inbounds []Inbound + err = json.Unmarshal(resp.Object, &inbounds) + if err != nil { + return err + } + + return nil +} + +type addClientRequest struct { + ID int `json:"id"` + Settings json.RawMessage `json:"settings"` +} + +type Client struct { + ID string `json:"id"` + Flow string `json:"flow"` + Email string `json:"email"` + LimitIP int64 `json:"limitIp"` + TotalGB int64 `json:"totalGB"` + ExpiryTime int64 `json:"expiryTime"` + Enable bool `json:"enable"` + TgID string `json:"tgId"` + SubID string `json:"subId"` + Reset int64 `json:"reset"` +} + +func (t *XUIPriovider) AddClientToInbound(ctx context.Context, inboundID int, clients []Client) error { + addReq := addClientRequest{ + ID: inboundID, + } + + settings := struct { + Clients []Client `json:"clients"` + }{ + Clients: clients, + } + var err error + addReq.Settings, err = json.Marshal(settings) + if err != nil { + return err + } + + var resp basicResponse + err = requests. + URL(t.baseUrl). + Path("panel/api/inbounds/addClient"). + Post(). + BodyJSON(addReq). + Client(t.client). + ToJSON(&resp). + Fetch(ctx) + if err != nil { + return err + } + + if !resp.Success { + return fmt.Errorf("logout failed: %s", resp.Message) + } + + return nil +}