package model import ( "one-api/common" "strconv" "strings" "time" ) type Option struct { Key string `json:"key" gorm:"primaryKey"` Value string `json:"value"` } func AllOption() ([]*Option, error) { var options []*Option var err error err = DB.Find(&options).Error return options, err } func InitOptionMap() { common.OptionMapRWMutex.Lock() common.OptionMap = make(map[string]string) common.OptionMap["FileUploadPermission"] = strconv.Itoa(common.FileUploadPermission) common.OptionMap["FileDownloadPermission"] = strconv.Itoa(common.FileDownloadPermission) common.OptionMap["ImageUploadPermission"] = strconv.Itoa(common.ImageUploadPermission) common.OptionMap["ImageDownloadPermission"] = strconv.Itoa(common.ImageDownloadPermission) common.OptionMap["PasswordLoginEnabled"] = strconv.FormatBool(common.PasswordLoginEnabled) common.OptionMap["PasswordRegisterEnabled"] = strconv.FormatBool(common.PasswordRegisterEnabled) common.OptionMap["EmailVerificationEnabled"] = strconv.FormatBool(common.EmailVerificationEnabled) common.OptionMap["GitHubOAuthEnabled"] = strconv.FormatBool(common.GitHubOAuthEnabled) common.OptionMap["WeChatAuthEnabled"] = strconv.FormatBool(common.WeChatAuthEnabled) common.OptionMap["TurnstileCheckEnabled"] = strconv.FormatBool(common.TurnstileCheckEnabled) common.OptionMap["RegisterEnabled"] = strconv.FormatBool(common.RegisterEnabled) common.OptionMap["AutomaticDisableChannelEnabled"] = strconv.FormatBool(common.AutomaticDisableChannelEnabled) common.OptionMap["ApproximateTokenEnabled"] = strconv.FormatBool(common.ApproximateTokenEnabled) common.OptionMap["LogConsumeEnabled"] = strconv.FormatBool(common.LogConsumeEnabled) common.OptionMap["DisplayInCurrencyEnabled"] = strconv.FormatBool(common.DisplayInCurrencyEnabled) common.OptionMap["DisplayTokenStatEnabled"] = strconv.FormatBool(common.DisplayTokenStatEnabled) common.OptionMap["ChannelDisableThreshold"] = strconv.FormatFloat(common.ChannelDisableThreshold, 'f', -1, 64) common.OptionMap["EmailDomainRestrictionEnabled"] = strconv.FormatBool(common.EmailDomainRestrictionEnabled) common.OptionMap["EmailDomainWhitelist"] = strings.Join(common.EmailDomainWhitelist, ",") common.OptionMap["SMTPServer"] = "" common.OptionMap["SMTPFrom"] = "" common.OptionMap["SMTPPort"] = strconv.Itoa(common.SMTPPort) common.OptionMap["SMTPAccount"] = "" common.OptionMap["SMTPToken"] = "" common.OptionMap["Notice"] = "" common.OptionMap["About"] = "" common.OptionMap["HomePageContent"] = "" common.OptionMap["Footer"] = common.Footer common.OptionMap["SystemName"] = common.SystemName common.OptionMap["Logo"] = common.Logo common.OptionMap["ServerAddress"] = "" common.OptionMap["GitHubClientId"] = "" common.OptionMap["GitHubClientSecret"] = "" common.OptionMap["WeChatServerAddress"] = "" common.OptionMap["WeChatServerToken"] = "" common.OptionMap["WeChatAccountQRCodeImageURL"] = "" common.OptionMap["TurnstileSiteKey"] = "" common.OptionMap["TurnstileSecretKey"] = "" common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser) common.OptionMap["QuotaForInviter"] = strconv.Itoa(common.QuotaForInviter) common.OptionMap["QuotaForInvitee"] = strconv.Itoa(common.QuotaForInvitee) common.OptionMap["QuotaRemindThreshold"] = strconv.Itoa(common.QuotaRemindThreshold) common.OptionMap["PreConsumedQuota"] = strconv.Itoa(common.PreConsumedQuota) common.OptionMap["ModelRatio"] = common.ModelRatio2JSONString() common.OptionMap["GroupRatio"] = common.GroupRatio2JSONString() common.OptionMap["TopUpLink"] = common.TopUpLink common.OptionMap["ChatLink"] = common.ChatLink common.OptionMap["QuotaPerUnit"] = strconv.FormatFloat(common.QuotaPerUnit, 'f', -1, 64) common.OptionMap["RetryTimes"] = strconv.Itoa(common.RetryTimes) common.OptionMapRWMutex.Unlock() loadOptionsFromDatabase() } func loadOptionsFromDatabase() { options, _ := AllOption() for _, option := range options { err := updateOptionMap(option.Key, option.Value) if err != nil { common.SysError("failed to update option map: " + err.Error()) } } } func SyncOptions(frequency int) { for { time.Sleep(time.Duration(frequency) * time.Second) common.SysLog("syncing options from database") loadOptionsFromDatabase() } } func UpdateOption(key string, value string) error { // Save to database first option := Option{ Key: key, } // https://gorm.io/docs/update.html#Save-All-Fields DB.FirstOrCreate(&option, Option{Key: key}) option.Value = value // Save is a combination function. // If save value does not contain primary key, it will execute Create, // otherwise it will execute Update (with all fields). DB.Save(&option) // Update OptionMap return updateOptionMap(key, value) } func updateOptionMap(key string, value string) (err error) { common.OptionMapRWMutex.Lock() defer common.OptionMapRWMutex.Unlock() common.OptionMap[key] = value if strings.HasSuffix(key, "Permission") { intValue, _ := strconv.Atoi(value) switch key { case "FileUploadPermission": common.FileUploadPermission = intValue case "FileDownloadPermission": common.FileDownloadPermission = intValue case "ImageUploadPermission": common.ImageUploadPermission = intValue case "ImageDownloadPermission": common.ImageDownloadPermission = intValue } } if strings.HasSuffix(key, "Enabled") { boolValue := value == "true" switch key { case "PasswordRegisterEnabled": common.PasswordRegisterEnabled = boolValue case "PasswordLoginEnabled": common.PasswordLoginEnabled = boolValue case "EmailVerificationEnabled": common.EmailVerificationEnabled = boolValue case "GitHubOAuthEnabled": common.GitHubOAuthEnabled = boolValue case "WeChatAuthEnabled": common.WeChatAuthEnabled = boolValue case "TurnstileCheckEnabled": common.TurnstileCheckEnabled = boolValue case "RegisterEnabled": common.RegisterEnabled = boolValue case "EmailDomainRestrictionEnabled": common.EmailDomainRestrictionEnabled = boolValue case "AutomaticDisableChannelEnabled": common.AutomaticDisableChannelEnabled = boolValue case "ApproximateTokenEnabled": common.ApproximateTokenEnabled = boolValue case "LogConsumeEnabled": common.LogConsumeEnabled = boolValue case "DisplayInCurrencyEnabled": common.DisplayInCurrencyEnabled = boolValue case "DisplayTokenStatEnabled": common.DisplayTokenStatEnabled = boolValue } } switch key { case "EmailDomainWhitelist": common.EmailDomainWhitelist = strings.Split(value, ",") case "SMTPServer": common.SMTPServer = value case "SMTPPort": intValue, _ := strconv.Atoi(value) common.SMTPPort = intValue case "SMTPAccount": common.SMTPAccount = value case "SMTPFrom": common.SMTPFrom = value case "SMTPToken": common.SMTPToken = value case "ServerAddress": common.ServerAddress = value case "GitHubClientId": common.GitHubClientId = value case "GitHubClientSecret": common.GitHubClientSecret = value case "Footer": common.Footer = value case "SystemName": common.SystemName = value case "Logo": common.Logo = value case "WeChatServerAddress": common.WeChatServerAddress = value case "WeChatServerToken": common.WeChatServerToken = value case "WeChatAccountQRCodeImageURL": common.WeChatAccountQRCodeImageURL = value case "TurnstileSiteKey": common.TurnstileSiteKey = value case "TurnstileSecretKey": common.TurnstileSecretKey = value case "QuotaForNewUser": common.QuotaForNewUser, _ = strconv.Atoi(value) case "QuotaForInviter": common.QuotaForInviter, _ = strconv.Atoi(value) case "QuotaForInvitee": common.QuotaForInvitee, _ = strconv.Atoi(value) case "QuotaRemindThreshold": common.QuotaRemindThreshold, _ = strconv.Atoi(value) case "PreConsumedQuota": common.PreConsumedQuota, _ = strconv.Atoi(value) case "RetryTimes": common.RetryTimes, _ = strconv.Atoi(value) case "ModelRatio": err = common.UpdateModelRatioByJSONString(value) case "GroupRatio": err = common.UpdateGroupRatioByJSONString(value) case "TopUpLink": common.TopUpLink = value case "ChatLink": common.ChatLink = value case "ChannelDisableThreshold": common.ChannelDisableThreshold, _ = strconv.ParseFloat(value, 64) case "QuotaPerUnit": common.QuotaPerUnit, _ = strconv.ParseFloat(value, 64) } return err }