Merge pull request #2121 from QuantumNous/feat/special_group

feat: add special user usable group setting
This commit is contained in:
Seefs
2025-10-29 18:54:51 +09:00
committed by GitHub
22 changed files with 521 additions and 142 deletions

View File

@@ -1,15 +1,17 @@
package setting
import "encoding/json"
import (
"github.com/QuantumNous/new-api/common"
)
var AutoGroups = []string{
var autoGroups = []string{
"default",
}
var DefaultUseAutoGroup = false
func ContainsAutoGroup(group string) bool {
for _, autoGroup := range AutoGroups {
for _, autoGroup := range autoGroups {
if autoGroup == group {
return true
}
@@ -18,14 +20,18 @@ func ContainsAutoGroup(group string) bool {
}
func UpdateAutoGroupsByJsonString(jsonString string) error {
AutoGroups = make([]string, 0)
return json.Unmarshal([]byte(jsonString), &AutoGroups)
autoGroups = make([]string, 0)
return common.Unmarshal([]byte(jsonString), &autoGroups)
}
func AutoGroups2JsonString() string {
jsonBytes, err := json.Marshal(AutoGroups)
jsonBytes, err := common.Marshal(autoGroups)
if err != nil {
return "[]"
}
return string(jsonBytes)
}
func GetAutoGroups() []string {
return autoGroups
}

View File

@@ -131,6 +131,18 @@ func configToMap(config interface{}) (map[string]string, error) {
strValue = strconv.FormatUint(field.Uint(), 10)
case reflect.Float32, reflect.Float64:
strValue = strconv.FormatFloat(field.Float(), 'f', -1, 64)
case reflect.Ptr:
// 处理指针类型:如果非 nil序列化指向的值
if !field.IsNil() {
bytes, err := json.Marshal(field.Interface())
if err != nil {
return nil, err
}
strValue = string(bytes)
} else {
// nil 指针序列化为 "null"
strValue = "null"
}
case reflect.Map, reflect.Slice, reflect.Struct:
// 复杂类型使用JSON序列化
bytes, err := json.Marshal(field.Interface())
@@ -215,6 +227,21 @@ func updateConfigFromMap(config interface{}, configMap map[string]string) error
continue
}
field.SetFloat(floatValue)
case reflect.Ptr:
// 处理指针类型
if strValue == "null" {
field.Set(reflect.Zero(field.Type()))
} else {
// 如果指针是 nil需要先初始化
if field.IsNil() {
field.Set(reflect.New(field.Type().Elem()))
}
// 反序列化到指针指向的值
err := json.Unmarshal([]byte(strValue), field.Interface())
if err != nil {
continue
}
}
case reflect.Map, reflect.Slice, reflect.Struct:
// 复杂类型使用JSON反序列化
err := json.Unmarshal([]byte(strValue), field.Addr().Interface())

View File

@@ -6,6 +6,8 @@ import (
"sync"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/setting/config"
"github.com/QuantumNous/new-api/types"
)
var groupRatio = map[string]float64{
@@ -13,6 +15,7 @@ var groupRatio = map[string]float64{
"vip": 1,
"svip": 1,
}
var groupRatioMutex sync.RWMutex
var (
@@ -24,6 +27,42 @@ var (
groupGroupRatioMutex sync.RWMutex
)
var defaultGroupSpecialUsableGroup = map[string]map[string]string{
"vip": {
"append_1": "vip_special_group_1",
"-:remove_1": "vip_removed_group_1",
},
}
type GroupRatioSetting struct {
GroupRatio map[string]float64 `json:"group_ratio"`
GroupGroupRatio map[string]map[string]float64 `json:"group_group_ratio"`
GroupSpecialUsableGroup *types.RWMap[string, map[string]string] `json:"group_special_usable_group"`
}
var groupRatioSetting GroupRatioSetting
func init() {
groupSpecialUsableGroup := types.NewRWMap[string, map[string]string]()
groupSpecialUsableGroup.AddAll(defaultGroupSpecialUsableGroup)
groupRatioSetting = GroupRatioSetting{
GroupSpecialUsableGroup: groupSpecialUsableGroup,
GroupRatio: groupRatio,
GroupGroupRatio: GroupGroupRatio,
}
config.GlobalConfig.Register("group_ratio_setting", &groupRatioSetting)
}
func GetGroupRatioSetting() *GroupRatioSetting {
if groupRatioSetting.GroupSpecialUsableGroup == nil {
groupRatioSetting.GroupSpecialUsableGroup = types.NewRWMap[string, map[string]string]()
groupRatioSetting.GroupSpecialUsableGroup.AddAll(defaultGroupSpecialUsableGroup)
}
return &groupRatioSetting
}
func GetGroupRatioCopy() map[string]float64 {
groupRatioMutex.RLock()
defer groupRatioMutex.RUnlock()

View File

@@ -43,29 +43,6 @@ func UpdateUserUsableGroupsByJSONString(jsonStr string) error {
return json.Unmarshal([]byte(jsonStr), &userUsableGroups)
}
func GetUserUsableGroups(userGroup string) map[string]string {
groupsCopy := GetUserUsableGroupsCopy()
if userGroup == "" {
if _, ok := groupsCopy["default"]; !ok {
groupsCopy["default"] = "default"
}
}
// 如果userGroup不在UserUsableGroups中返回UserUsableGroups + userGroup
if _, ok := groupsCopy[userGroup]; !ok {
groupsCopy[userGroup] = "用户分组"
}
// 如果userGroup在UserUsableGroups中返回UserUsableGroups
return groupsCopy
}
func GroupInUserUsableGroups(groupName string) bool {
userUsableGroupsMutex.RLock()
defer userUsableGroupsMutex.RUnlock()
_, ok := userUsableGroups[groupName]
return ok
}
func GetUsableGroupDescription(groupName string) string {
userUsableGroupsMutex.RLock()
defer userUsableGroupsMutex.RUnlock()