| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 | 
							- package service
 
- import (
 
- 	_ "embed"
 
- 	"encoding/json"
 
- 	"errors"
 
- 	"fmt"
 
- 	"reflect"
 
- 	"strconv"
 
- 	"strings"
 
- 	"time"
 
- 	"github.com/mhsanaei/3x-ui/v2/database"
 
- 	"github.com/mhsanaei/3x-ui/v2/database/model"
 
- 	"github.com/mhsanaei/3x-ui/v2/logger"
 
- 	"github.com/mhsanaei/3x-ui/v2/util/common"
 
- 	"github.com/mhsanaei/3x-ui/v2/util/random"
 
- 	"github.com/mhsanaei/3x-ui/v2/util/reflect_util"
 
- 	"github.com/mhsanaei/3x-ui/v2/web/entity"
 
- 	"github.com/mhsanaei/3x-ui/v2/xray"
 
- )
 
- //go:embed config.json
 
- var xrayTemplateConfig string
 
- var defaultValueMap = map[string]string{
 
- 	"xrayTemplateConfig":          xrayTemplateConfig,
 
- 	"webListen":                   "",
 
- 	"webDomain":                   "",
 
- 	"webPort":                     "2053",
 
- 	"webCertFile":                 "",
 
- 	"webKeyFile":                  "",
 
- 	"secret":                      random.Seq(32),
 
- 	"webBasePath":                 "/",
 
- 	"sessionMaxAge":               "360",
 
- 	"pageSize":                    "25",
 
- 	"expireDiff":                  "0",
 
- 	"trafficDiff":                 "0",
 
- 	"remarkModel":                 "-ieo",
 
- 	"timeLocation":                "Local",
 
- 	"tgBotEnable":                 "false",
 
- 	"tgBotToken":                  "",
 
- 	"tgBotProxy":                  "",
 
- 	"tgBotAPIServer":              "",
 
- 	"tgBotChatId":                 "",
 
- 	"tgRunTime":                   "@daily",
 
- 	"tgBotBackup":                 "false",
 
- 	"tgBotLoginNotify":            "true",
 
- 	"tgCpu":                       "80",
 
- 	"tgLang":                      "en-US",
 
- 	"twoFactorEnable":             "false",
 
- 	"twoFactorToken":              "",
 
- 	"subEnable":                   "true",
 
- 	"subJsonEnable":               "false",
 
- 	"subTitle":                    "",
 
- 	"subListen":                   "",
 
- 	"subPort":                     "2096",
 
- 	"subPath":                     "/sub/",
 
- 	"subDomain":                   "",
 
- 	"subCertFile":                 "",
 
- 	"subKeyFile":                  "",
 
- 	"subUpdates":                  "12",
 
- 	"subEncrypt":                  "true",
 
- 	"subShowInfo":                 "true",
 
- 	"subURI":                      "",
 
- 	"subJsonPath":                 "/json/",
 
- 	"subJsonURI":                  "",
 
- 	"subJsonFragment":             "",
 
- 	"subJsonNoises":               "",
 
- 	"subJsonMux":                  "",
 
- 	"subJsonRules":                "",
 
- 	"datepicker":                  "gregorian",
 
- 	"warp":                        "",
 
- 	"externalTrafficInformEnable": "false",
 
- 	"externalTrafficInformURI":    "",
 
- 	// LDAP defaults
 
- 	"ldapEnable":            "false",
 
- 	"ldapHost":              "",
 
- 	"ldapPort":              "389",
 
- 	"ldapUseTLS":            "false",
 
- 	"ldapBindDN":            "",
 
- 	"ldapPassword":          "",
 
- 	"ldapBaseDN":            "",
 
- 	"ldapUserFilter":        "(objectClass=person)",
 
- 	"ldapUserAttr":          "mail",
 
- 	"ldapVlessField":        "vless_enabled",
 
- 	"ldapSyncCron":          "@every 1m",
 
- 	"ldapFlagField":         "",
 
- 	"ldapTruthyValues":      "true,1,yes,on",
 
- 	"ldapInvertFlag":        "false",
 
- 	"ldapInboundTags":       "",
 
- 	"ldapAutoCreate":        "false",
 
- 	"ldapAutoDelete":        "false",
 
- 	"ldapDefaultTotalGB":    "0",
 
- 	"ldapDefaultExpiryDays": "0",
 
- 	"ldapDefaultLimitIP":    "0",
 
- }
 
- // SettingService provides business logic for application settings management.
 
- // It handles configuration storage, retrieval, and validation for all system settings.
 
- type SettingService struct{}
 
- func (s *SettingService) GetDefaultJsonConfig() (any, error) {
 
- 	var jsonData any
 
- 	err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return jsonData, nil
 
- }
 
- func (s *SettingService) GetAllSetting() (*entity.AllSetting, error) {
 
- 	db := database.GetDB()
 
- 	settings := make([]*model.Setting, 0)
 
- 	err := db.Model(model.Setting{}).Not("key = ?", "xrayTemplateConfig").Find(&settings).Error
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	allSetting := &entity.AllSetting{}
 
- 	t := reflect.TypeOf(allSetting).Elem()
 
- 	v := reflect.ValueOf(allSetting).Elem()
 
- 	fields := reflect_util.GetFields(t)
 
- 	setSetting := func(key, value string) (err error) {
 
- 		defer func() {
 
- 			panicErr := recover()
 
- 			if panicErr != nil {
 
- 				err = errors.New(fmt.Sprint(panicErr))
 
- 			}
 
- 		}()
 
- 		var found bool
 
- 		var field reflect.StructField
 
- 		for _, f := range fields {
 
- 			if f.Tag.Get("json") == key {
 
- 				field = f
 
- 				found = true
 
- 				break
 
- 			}
 
- 		}
 
- 		if !found {
 
- 			// Some settings are automatically generated, no need to return to the front end to modify the user
 
- 			return nil
 
- 		}
 
- 		fieldV := v.FieldByName(field.Name)
 
- 		switch t := fieldV.Interface().(type) {
 
- 		case int:
 
- 			n, err := strconv.ParseInt(value, 10, 64)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			fieldV.SetInt(n)
 
- 		case string:
 
- 			fieldV.SetString(value)
 
- 		case bool:
 
- 			fieldV.SetBool(value == "true")
 
- 		default:
 
- 			return common.NewErrorf("unknown field %v type %v", key, t)
 
- 		}
 
- 		return
 
- 	}
 
- 	keyMap := map[string]bool{}
 
- 	for _, setting := range settings {
 
- 		err := setSetting(setting.Key, setting.Value)
 
- 		if err != nil {
 
- 			return nil, err
 
- 		}
 
- 		keyMap[setting.Key] = true
 
- 	}
 
- 	for key, value := range defaultValueMap {
 
- 		if keyMap[key] {
 
- 			continue
 
- 		}
 
- 		err := setSetting(key, value)
 
- 		if err != nil {
 
- 			return nil, err
 
- 		}
 
- 	}
 
- 	return allSetting, nil
 
- }
 
- func (s *SettingService) ResetSettings() error {
 
- 	db := database.GetDB()
 
- 	err := db.Where("1 = 1").Delete(model.Setting{}).Error
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return db.Model(model.User{}).
 
- 		Where("1 = 1").Error
 
- }
 
- func (s *SettingService) getSetting(key string) (*model.Setting, error) {
 
- 	db := database.GetDB()
 
- 	setting := &model.Setting{}
 
- 	err := db.Model(model.Setting{}).Where("key = ?", key).First(setting).Error
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return setting, nil
 
- }
 
- func (s *SettingService) saveSetting(key string, value string) error {
 
- 	setting, err := s.getSetting(key)
 
- 	db := database.GetDB()
 
- 	if database.IsNotFound(err) {
 
- 		return db.Create(&model.Setting{
 
- 			Key:   key,
 
- 			Value: value,
 
- 		}).Error
 
- 	} else if err != nil {
 
- 		return err
 
- 	}
 
- 	setting.Key = key
 
- 	setting.Value = value
 
- 	return db.Save(setting).Error
 
- }
 
- func (s *SettingService) getString(key string) (string, error) {
 
- 	setting, err := s.getSetting(key)
 
- 	if database.IsNotFound(err) {
 
- 		value, ok := defaultValueMap[key]
 
- 		if !ok {
 
- 			return "", common.NewErrorf("key <%v> not in defaultValueMap", key)
 
- 		}
 
- 		return value, nil
 
- 	} else if err != nil {
 
- 		return "", err
 
- 	}
 
- 	return setting.Value, nil
 
- }
 
- func (s *SettingService) setString(key string, value string) error {
 
- 	return s.saveSetting(key, value)
 
- }
 
- func (s *SettingService) getBool(key string) (bool, error) {
 
- 	str, err := s.getString(key)
 
- 	if err != nil {
 
- 		return false, err
 
- 	}
 
- 	return strconv.ParseBool(str)
 
- }
 
- func (s *SettingService) setBool(key string, value bool) error {
 
- 	return s.setString(key, strconv.FormatBool(value))
 
- }
 
- func (s *SettingService) getInt(key string) (int, error) {
 
- 	str, err := s.getString(key)
 
- 	if err != nil {
 
- 		return 0, err
 
- 	}
 
- 	return strconv.Atoi(str)
 
- }
 
- func (s *SettingService) setInt(key string, value int) error {
 
- 	return s.setString(key, strconv.Itoa(value))
 
- }
 
- func (s *SettingService) GetXrayConfigTemplate() (string, error) {
 
- 	return s.getString("xrayTemplateConfig")
 
- }
 
- func (s *SettingService) GetListen() (string, error) {
 
- 	return s.getString("webListen")
 
- }
 
- func (s *SettingService) SetListen(ip string) error {
 
- 	return s.setString("webListen", ip)
 
- }
 
- func (s *SettingService) GetWebDomain() (string, error) {
 
- 	return s.getString("webDomain")
 
- }
 
- func (s *SettingService) GetTgBotToken() (string, error) {
 
- 	return s.getString("tgBotToken")
 
- }
 
- func (s *SettingService) SetTgBotToken(token string) error {
 
- 	return s.setString("tgBotToken", token)
 
- }
 
- func (s *SettingService) GetTgBotProxy() (string, error) {
 
- 	return s.getString("tgBotProxy")
 
- }
 
- func (s *SettingService) SetTgBotProxy(token string) error {
 
- 	return s.setString("tgBotProxy", token)
 
- }
 
- func (s *SettingService) GetTgBotAPIServer() (string, error) {
 
- 	return s.getString("tgBotAPIServer")
 
- }
 
- func (s *SettingService) SetTgBotAPIServer(token string) error {
 
- 	return s.setString("tgBotAPIServer", token)
 
- }
 
- func (s *SettingService) GetTgBotChatId() (string, error) {
 
- 	return s.getString("tgBotChatId")
 
- }
 
- func (s *SettingService) SetTgBotChatId(chatIds string) error {
 
- 	return s.setString("tgBotChatId", chatIds)
 
- }
 
- func (s *SettingService) GetTgbotEnabled() (bool, error) {
 
- 	return s.getBool("tgBotEnable")
 
- }
 
- func (s *SettingService) SetTgbotEnabled(value bool) error {
 
- 	return s.setBool("tgBotEnable", value)
 
- }
 
- func (s *SettingService) GetTgbotRuntime() (string, error) {
 
- 	return s.getString("tgRunTime")
 
- }
 
- func (s *SettingService) SetTgbotRuntime(time string) error {
 
- 	return s.setString("tgRunTime", time)
 
- }
 
- func (s *SettingService) GetTgBotBackup() (bool, error) {
 
- 	return s.getBool("tgBotBackup")
 
- }
 
- func (s *SettingService) GetTgBotLoginNotify() (bool, error) {
 
- 	return s.getBool("tgBotLoginNotify")
 
- }
 
- func (s *SettingService) GetTgCpu() (int, error) {
 
- 	return s.getInt("tgCpu")
 
- }
 
- func (s *SettingService) GetTgLang() (string, error) {
 
- 	return s.getString("tgLang")
 
- }
 
- func (s *SettingService) GetTwoFactorEnable() (bool, error) {
 
- 	return s.getBool("twoFactorEnable")
 
- }
 
- func (s *SettingService) SetTwoFactorEnable(value bool) error {
 
- 	return s.setBool("twoFactorEnable", value)
 
- }
 
- func (s *SettingService) GetTwoFactorToken() (string, error) {
 
- 	return s.getString("twoFactorToken")
 
- }
 
- func (s *SettingService) SetTwoFactorToken(value string) error {
 
- 	return s.setString("twoFactorToken", value)
 
- }
 
- func (s *SettingService) GetPort() (int, error) {
 
- 	return s.getInt("webPort")
 
- }
 
- func (s *SettingService) SetPort(port int) error {
 
- 	return s.setInt("webPort", port)
 
- }
 
- func (s *SettingService) SetCertFile(webCertFile string) error {
 
- 	return s.setString("webCertFile", webCertFile)
 
- }
 
- func (s *SettingService) GetCertFile() (string, error) {
 
- 	return s.getString("webCertFile")
 
- }
 
- func (s *SettingService) SetKeyFile(webKeyFile string) error {
 
- 	return s.setString("webKeyFile", webKeyFile)
 
- }
 
- func (s *SettingService) GetKeyFile() (string, error) {
 
- 	return s.getString("webKeyFile")
 
- }
 
- func (s *SettingService) GetExpireDiff() (int, error) {
 
- 	return s.getInt("expireDiff")
 
- }
 
- func (s *SettingService) GetTrafficDiff() (int, error) {
 
- 	return s.getInt("trafficDiff")
 
- }
 
- func (s *SettingService) GetSessionMaxAge() (int, error) {
 
- 	return s.getInt("sessionMaxAge")
 
- }
 
- func (s *SettingService) GetRemarkModel() (string, error) {
 
- 	return s.getString("remarkModel")
 
- }
 
- func (s *SettingService) GetSecret() ([]byte, error) {
 
- 	secret, err := s.getString("secret")
 
- 	if secret == defaultValueMap["secret"] {
 
- 		err := s.saveSetting("secret", secret)
 
- 		if err != nil {
 
- 			logger.Warning("save secret failed:", err)
 
- 		}
 
- 	}
 
- 	return []byte(secret), err
 
- }
 
- func (s *SettingService) SetBasePath(basePath string) error {
 
- 	if !strings.HasPrefix(basePath, "/") {
 
- 		basePath = "/" + basePath
 
- 	}
 
- 	if !strings.HasSuffix(basePath, "/") {
 
- 		basePath += "/"
 
- 	}
 
- 	return s.setString("webBasePath", basePath)
 
- }
 
- func (s *SettingService) GetBasePath() (string, error) {
 
- 	basePath, err := s.getString("webBasePath")
 
- 	if err != nil {
 
- 		return "", err
 
- 	}
 
- 	if !strings.HasPrefix(basePath, "/") {
 
- 		basePath = "/" + basePath
 
- 	}
 
- 	if !strings.HasSuffix(basePath, "/") {
 
- 		basePath += "/"
 
- 	}
 
- 	return basePath, nil
 
- }
 
- func (s *SettingService) GetTimeLocation() (*time.Location, error) {
 
- 	l, err := s.getString("timeLocation")
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	location, err := time.LoadLocation(l)
 
- 	if err != nil {
 
- 		defaultLocation := defaultValueMap["timeLocation"]
 
- 		logger.Errorf("location <%v> not exist, using default location: %v", l, defaultLocation)
 
- 		return time.LoadLocation(defaultLocation)
 
- 	}
 
- 	return location, nil
 
- }
 
- func (s *SettingService) GetSubEnable() (bool, error) {
 
- 	return s.getBool("subEnable")
 
- }
 
- func (s *SettingService) GetSubJsonEnable() (bool, error) {
 
- 	return s.getBool("subJsonEnable")
 
- }
 
- func (s *SettingService) GetSubTitle() (string, error) {
 
- 	return s.getString("subTitle")
 
- }
 
- func (s *SettingService) GetSubListen() (string, error) {
 
- 	return s.getString("subListen")
 
- }
 
- func (s *SettingService) GetSubPort() (int, error) {
 
- 	return s.getInt("subPort")
 
- }
 
- func (s *SettingService) GetSubPath() (string, error) {
 
- 	return s.getString("subPath")
 
- }
 
- func (s *SettingService) GetSubJsonPath() (string, error) {
 
- 	return s.getString("subJsonPath")
 
- }
 
- func (s *SettingService) GetSubDomain() (string, error) {
 
- 	return s.getString("subDomain")
 
- }
 
- func (s *SettingService) GetSubCertFile() (string, error) {
 
- 	return s.getString("subCertFile")
 
- }
 
- func (s *SettingService) GetSubKeyFile() (string, error) {
 
- 	return s.getString("subKeyFile")
 
- }
 
- func (s *SettingService) GetSubUpdates() (string, error) {
 
- 	return s.getString("subUpdates")
 
- }
 
- func (s *SettingService) GetSubEncrypt() (bool, error) {
 
- 	return s.getBool("subEncrypt")
 
- }
 
- func (s *SettingService) GetSubShowInfo() (bool, error) {
 
- 	return s.getBool("subShowInfo")
 
- }
 
- func (s *SettingService) GetPageSize() (int, error) {
 
- 	return s.getInt("pageSize")
 
- }
 
- func (s *SettingService) GetSubURI() (string, error) {
 
- 	return s.getString("subURI")
 
- }
 
- func (s *SettingService) GetSubJsonURI() (string, error) {
 
- 	return s.getString("subJsonURI")
 
- }
 
- func (s *SettingService) GetSubJsonFragment() (string, error) {
 
- 	return s.getString("subJsonFragment")
 
- }
 
- func (s *SettingService) GetSubJsonNoises() (string, error) {
 
- 	return s.getString("subJsonNoises")
 
- }
 
- func (s *SettingService) GetSubJsonMux() (string, error) {
 
- 	return s.getString("subJsonMux")
 
- }
 
- func (s *SettingService) GetSubJsonRules() (string, error) {
 
- 	return s.getString("subJsonRules")
 
- }
 
- func (s *SettingService) GetDatepicker() (string, error) {
 
- 	return s.getString("datepicker")
 
- }
 
- func (s *SettingService) GetWarp() (string, error) {
 
- 	return s.getString("warp")
 
- }
 
- func (s *SettingService) SetWarp(data string) error {
 
- 	return s.setString("warp", data)
 
- }
 
- func (s *SettingService) GetExternalTrafficInformEnable() (bool, error) {
 
- 	return s.getBool("externalTrafficInformEnable")
 
- }
 
- func (s *SettingService) SetExternalTrafficInformEnable(value bool) error {
 
- 	return s.setBool("externalTrafficInformEnable", value)
 
- }
 
- func (s *SettingService) GetExternalTrafficInformURI() (string, error) {
 
- 	return s.getString("externalTrafficInformURI")
 
- }
 
- func (s *SettingService) SetExternalTrafficInformURI(InformURI string) error {
 
- 	return s.setString("externalTrafficInformURI", InformURI)
 
- }
 
- func (s *SettingService) GetIpLimitEnable() (bool, error) {
 
- 	accessLogPath, err := xray.GetAccessLogPath()
 
- 	if err != nil {
 
- 		return false, err
 
- 	}
 
- 	return (accessLogPath != "none" && accessLogPath != ""), nil
 
- }
 
- // LDAP exported getters
 
- func (s *SettingService) GetLdapEnable() (bool, error) {
 
- 	return s.getBool("ldapEnable")
 
- }
 
- func (s *SettingService) GetLdapHost() (string, error) {
 
- 	return s.getString("ldapHost")
 
- }
 
- func (s *SettingService) GetLdapPort() (int, error) {
 
- 	return s.getInt("ldapPort")
 
- }
 
- func (s *SettingService) GetLdapUseTLS() (bool, error) {
 
- 	return s.getBool("ldapUseTLS")
 
- }
 
- func (s *SettingService) GetLdapBindDN() (string, error) {
 
- 	return s.getString("ldapBindDN")
 
- }
 
- func (s *SettingService) GetLdapPassword() (string, error) {
 
- 	return s.getString("ldapPassword")
 
- }
 
- func (s *SettingService) GetLdapBaseDN() (string, error) {
 
- 	return s.getString("ldapBaseDN")
 
- }
 
- func (s *SettingService) GetLdapUserFilter() (string, error) {
 
- 	return s.getString("ldapUserFilter")
 
- }
 
- func (s *SettingService) GetLdapUserAttr() (string, error) {
 
- 	return s.getString("ldapUserAttr")
 
- }
 
- func (s *SettingService) GetLdapVlessField() (string, error) {
 
- 	return s.getString("ldapVlessField")
 
- }
 
- func (s *SettingService) GetLdapSyncCron() (string, error) {
 
- 	return s.getString("ldapSyncCron")
 
- }
 
- func (s *SettingService) GetLdapFlagField() (string, error) {
 
- 	return s.getString("ldapFlagField")
 
- }
 
- func (s *SettingService) GetLdapTruthyValues() (string, error) {
 
- 	return s.getString("ldapTruthyValues")
 
- }
 
- func (s *SettingService) GetLdapInvertFlag() (bool, error) {
 
- 	return s.getBool("ldapInvertFlag")
 
- }
 
- func (s *SettingService) GetLdapInboundTags() (string, error) {
 
- 	return s.getString("ldapInboundTags")
 
- }
 
- func (s *SettingService) GetLdapAutoCreate() (bool, error) {
 
- 	return s.getBool("ldapAutoCreate")
 
- }
 
- func (s *SettingService) GetLdapAutoDelete() (bool, error) {
 
- 	return s.getBool("ldapAutoDelete")
 
- }
 
- func (s *SettingService) GetLdapDefaultTotalGB() (int, error) {
 
- 	return s.getInt("ldapDefaultTotalGB")
 
- }
 
- func (s *SettingService) GetLdapDefaultExpiryDays() (int, error) {
 
- 	return s.getInt("ldapDefaultExpiryDays")
 
- }
 
- func (s *SettingService) GetLdapDefaultLimitIP() (int, error) {
 
- 	return s.getInt("ldapDefaultLimitIP")
 
- }
 
- func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
 
- 	if err := allSetting.CheckValid(); err != nil {
 
- 		return err
 
- 	}
 
- 	v := reflect.ValueOf(allSetting).Elem()
 
- 	t := reflect.TypeOf(allSetting).Elem()
 
- 	fields := reflect_util.GetFields(t)
 
- 	errs := make([]error, 0)
 
- 	for _, field := range fields {
 
- 		key := field.Tag.Get("json")
 
- 		fieldV := v.FieldByName(field.Name)
 
- 		value := fmt.Sprint(fieldV.Interface())
 
- 		err := s.saveSetting(key, value)
 
- 		if err != nil {
 
- 			errs = append(errs, err)
 
- 		}
 
- 	}
 
- 	return common.Combine(errs...)
 
- }
 
- func (s *SettingService) GetDefaultXrayConfig() (any, error) {
 
- 	var jsonData any
 
- 	err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return jsonData, nil
 
- }
 
- func (s *SettingService) GetDefaultSettings(host string) (any, error) {
 
- 	type settingFunc func() (any, error)
 
- 	settings := map[string]settingFunc{
 
- 		"expireDiff":    func() (any, error) { return s.GetExpireDiff() },
 
- 		"trafficDiff":   func() (any, error) { return s.GetTrafficDiff() },
 
- 		"pageSize":      func() (any, error) { return s.GetPageSize() },
 
- 		"defaultCert":   func() (any, error) { return s.GetCertFile() },
 
- 		"defaultKey":    func() (any, error) { return s.GetKeyFile() },
 
- 		"tgBotEnable":   func() (any, error) { return s.GetTgbotEnabled() },
 
- 		"subEnable":     func() (any, error) { return s.GetSubEnable() },
 
- 		"subJsonEnable": func() (any, error) { return s.GetSubJsonEnable() },
 
- 		"subTitle":      func() (any, error) { return s.GetSubTitle() },
 
- 		"subURI":        func() (any, error) { return s.GetSubURI() },
 
- 		"subJsonURI":    func() (any, error) { return s.GetSubJsonURI() },
 
- 		"remarkModel":   func() (any, error) { return s.GetRemarkModel() },
 
- 		"datepicker":    func() (any, error) { return s.GetDatepicker() },
 
- 		"ipLimitEnable": func() (any, error) { return s.GetIpLimitEnable() },
 
- 	}
 
- 	result := make(map[string]any)
 
- 	for key, fn := range settings {
 
- 		value, err := fn()
 
- 		if err != nil {
 
- 			return "", err
 
- 		}
 
- 		result[key] = value
 
- 	}
 
- 	subEnable := result["subEnable"].(bool)
 
- 	subJsonEnable := false
 
- 	if v, ok := result["subJsonEnable"]; ok {
 
- 		if b, ok2 := v.(bool); ok2 {
 
- 			subJsonEnable = b
 
- 		}
 
- 	}
 
- 	if (subEnable && result["subURI"].(string) == "") || (subJsonEnable && result["subJsonURI"].(string) == "") {
 
- 		subURI := ""
 
- 		subTitle, _ := s.GetSubTitle()
 
- 		subPort, _ := s.GetSubPort()
 
- 		subPath, _ := s.GetSubPath()
 
- 		subJsonPath, _ := s.GetSubJsonPath()
 
- 		subDomain, _ := s.GetSubDomain()
 
- 		subKeyFile, _ := s.GetSubKeyFile()
 
- 		subCertFile, _ := s.GetSubCertFile()
 
- 		subTLS := false
 
- 		if subKeyFile != "" && subCertFile != "" {
 
- 			subTLS = true
 
- 		}
 
- 		if subDomain == "" {
 
- 			subDomain = strings.Split(host, ":")[0]
 
- 		}
 
- 		if subTLS {
 
- 			subURI = "https://"
 
- 		} else {
 
- 			subURI = "http://"
 
- 		}
 
- 		if (subPort == 443 && subTLS) || (subPort == 80 && !subTLS) {
 
- 			subURI += subDomain
 
- 		} else {
 
- 			subURI += fmt.Sprintf("%s:%d", subDomain, subPort)
 
- 		}
 
- 		if subEnable && result["subURI"].(string) == "" {
 
- 			result["subURI"] = subURI + subPath
 
- 		}
 
- 		if result["subTitle"].(string) == "" {
 
- 			result["subTitle"] = subTitle
 
- 		}
 
- 		if subJsonEnable && result["subJsonURI"].(string) == "" {
 
- 			result["subJsonURI"] = subURI + subJsonPath
 
- 		}
 
- 	}
 
- 	return result, nil
 
- }
 
 
  |