Добавил изменения конфига

This commit is contained in:
B4D_US3R 2025-05-05 15:40:58 +05:00
parent b6866f8540
commit 4c2f052d70
5 changed files with 223 additions and 62 deletions

View file

@ -4,6 +4,14 @@ go 1.24.2
replace miku/users => ../users/
require miku/users v0.0.0-00010101000000-000000000000
require (
github.com/urfave/cli/v3 v3.3.2
miku/supporter v0.0.0-00010101000000-000000000000
)
require github.com/google/uuid v1.6.0 // indirect
require (
github.com/google/uuid v1.6.0 // indirect
miku/users v0.0.0-00010101000000-000000000000 // indirect
)
replace miku/supporter => ../supporter

View file

@ -1,28 +1,142 @@
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"miku/users"
"os"
"path/filepath"
"miku/supporter"
"github.com/urfave/cli/v3"
)
func main() {
var confFile map[string]interface{}
file, err := os.ReadFile("../testconfig.json")
if err != nil {
fmt.Println(err)
cmd := &cli.Command{
Name: "miku",
Usage: "Управление пользователями Vless в конфиге sing-box",
Commands: []*cli.Command{
{
Name: "add",
Aliases: []string{"a"},
Usage: "Добавить пользователя в config.json",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Value: "/etc/sing-box/config.json",
Usage: "Указывает местоположение конфига",
},
&cli.StringFlag{
Name: "domain",
Aliases: []string{"d"},
Value: "vpn.catgirls.asia",
Usage: "Указывает доменное имя, по которому клиенты могут выполнять подключение",
},
},
Action: func(ctx context.Context, c *cli.Command) error {
var confFile map[string]any
configPath, ok := c.Flags[0].Get().(string)
if !ok {
return errors.New("не удалось преобразовать тип")
}
err = json.Unmarshal(file, &confFile)
fullpath, err := filepath.Abs(configPath)
if err != nil {
fmt.Println(err)
return nil
}
vlessUsers := users.MapToStruct(confFile)
newUsers := vlessUsers.Add("test")
newConfFile, err := users.StructToConfig(newUsers, confFile)
fmt.Println(fullpath)
file, err := os.ReadFile(fullpath)
if err != nil {
log.Println(err)
return err
}
json.Unmarshal(file, &confFile)
vlessUsers, err := supporter.MapToStruct(confFile)
if err != nil {
return err
}
vlessUsers, err = vlessUsers.Add(c.Args().First())
if err != nil {
return err
}
fileToWrite, err := os.OpenFile(fullpath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
if err != nil {
return err
}
newConfig, err := supporter.StructToConfig(vlessUsers, confFile)
if err != nil {
return err
}
newJson, err := json.MarshalIndent(newConfig, "", "\t")
if err != nil {
return nil
}
fileToWrite.Write(newJson)
fmt.Printf("Пользователь %s добавлен в конфиг %s", c.Args().First(), fullpath)
return nil
},
},
{
Name: "delete",
Aliases: []string{"del", "d"},
Usage: "Удаление пользователя из конфига Vless",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Value: "/etc/sing-box/config.json",
Usage: "Указывает местоположение конфига",
},
&cli.StringFlag{
Name: "domain",
Aliases: []string{"d"},
Value: "vpn.catgirls.asia",
Usage: "Указывает доменное имя, по которому клиенты могут выполнять подключение",
},
},
Action: func(ctx context.Context, c *cli.Command) error {
var confFile map[string]any
configPath, ok := c.Flags[0].Get().(string)
if !ok {
return errors.New("не удалось преобразовать тип")
}
fullpath, err := filepath.Abs(configPath)
if err != nil {
return nil
}
fmt.Println(fullpath)
file, err := os.ReadFile(fullpath)
if err != nil {
return err
}
json.Unmarshal(file, &confFile)
vlessUsers, err := supporter.MapToStruct(confFile)
if err != nil {
return err
}
vlessUsers = vlessUsers.Del(c.Args().First())
fileToWrite, err := os.OpenFile(fullpath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
if err != nil {
return err
}
newConfig, err := supporter.StructToConfig(vlessUsers, confFile)
if err != nil {
return err
}
newJson, err := json.MarshalIndent(newConfig, "", "\t")
if err != nil {
return nil
}
fileToWrite.Write(newJson)
fmt.Printf("Пользователь %s удален из конфига %s", c.Args().First(), fullpath)
return nil
},
},
},
}
if err := cmd.Run(context.Background(), os.Args); err != nil {
log.Fatal(err)
}
log.Println(newConfFile)
}

10
supporter/go.mod Normal file
View file

@ -0,0 +1,10 @@
module miku/supporter
go 1.24.2
require (
github.com/google/uuid v1.6.0
miku/users v0.0.0-00010101000000-000000000000
)
replace miku/users => ../users

52
supporter/supporter.go Normal file
View file

@ -0,0 +1,52 @@
package supporter
import (
"encoding/json"
"errors"
"miku/users"
"github.com/google/uuid"
)
func MapToStruct(toStructMap map[string]any) (users.VLESSUsers, error) {
var vlessUsers users.VLESSUsers
inbounds, ok := toStructMap["inbounds"].([]any)
if !ok || len(inbounds) == 0 {
return nil, errors.New("нет inbounds")
}
firstInbound, ok := inbounds[0].(map[string]any)
if !ok || len(firstInbound) == 0 {
return nil, errors.New("неизвестный формат inbound")
}
usedMap, ok := firstInbound["users"].([]any)
if !ok || len(usedMap) == 0 {
return nil, errors.New("неизвестный формат пользователей")
}
for _, curretMap := range usedMap {
userMap := curretMap.(map[string]any)
vlessUsers = append(vlessUsers, struct {
Name string "json:\"name\""
UUID uuid.UUID "json:\"uuid\""
}{
Name: userMap["name"].(string),
UUID: uuid.MustParse(userMap["uuid"].(string)),
})
}
return vlessUsers, nil
}
func StructToConfig(vlessUsers users.VLESSUsers, configMap map[string]any) (map[string]any, error) {
var toInterface []map[string]any
newConfigMap := configMap
structJson, err := json.Marshal(vlessUsers)
if err != nil {
return nil, err
}
err = json.Unmarshal(structJson, &toInterface)
if err != nil {
return nil, err
}
newConfigMap["inbounds"].([]any)[0].(map[string]any)["users"] = toInterface
return newConfigMap, nil
}

View file

@ -1,19 +1,20 @@
package users
import (
"encoding/json"
"log"
"errors"
"github.com/google/uuid"
)
type VLESSUsers []struct {
type User struct {
Name string `json:"name"`
UUID uuid.UUID `json:"uuid"`
}
type VLESSUsers []User
func (u VLESSUsers) Del(user string) VLESSUsers {
var newU VLESSUsers
var newU VLESSUsers = make(VLESSUsers, 0, len(u))
for _, v := range u {
if v.Name != user {
newU = append(newU, v)
@ -22,52 +23,28 @@ func (u VLESSUsers) Del(user string) VLESSUsers {
return newU
}
func (u VLESSUsers) Add(user string) VLESSUsers {
var userStruct struct {
Name string
UUID uuid.UUID
func (u VLESSUsers) checkInConfig(userName string) bool {
for _, v := range u {
if v.Name == userName {
return true
}
userStruct.Name = user
randUUID, err := uuid.NewUUID()
if err != nil {
log.Println(err)
}
userStruct.UUID = randUUID
newU := append(u, struct {
Name string "json:\"name\""
UUID uuid.UUID "json:\"uuid\""
}(userStruct))
return newU
return false
}
func MapToStruct(toStructMap map[string]interface{}) VLESSUsers {
var vlessUsers VLESSUsers
usedMap := toStructMap["inbounds"].([]interface{})[0].(map[string]interface{})["users"].([]interface{})
for _, curretMap := range usedMap {
userMap := curretMap.(map[string]interface{})
vlessUsers = append(vlessUsers, struct {
Name string "json:\"name\""
UUID uuid.UUID "json:\"uuid\""
}{
Name: userMap["name"].(string),
UUID: uuid.MustParse(userMap["uuid"].(string)),
})
}
return vlessUsers
}
func (u VLESSUsers) Add(userName string) (VLESSUsers, error) {
func StructToConfig(vlessUsers VLESSUsers, configMap map[string]interface{}) (map[string]interface{}, error) {
var toInterface []map[string]interface{}
newConfigMap := configMap
structJson, err := json.Marshal(vlessUsers)
if err != nil {
return map[string]interface{}{}, err
if u.checkInConfig(userName) {
return nil, errors.New("пользователь уже добавлен в конфиг")
}
err = json.Unmarshal(structJson, &toInterface)
newUUID, err := uuid.NewRandom()
if err != nil {
return map[string]interface{}{}, err
return nil, err
}
newConfigMap["inbounds"].([]interface{})[0].(map[string]interface{})["users"] = toInterface
return newConfigMap, nil
newUser := User{
Name: userName,
UUID: newUUID,
}
return append(u, newUser), nil
}