first commit
This commit is contained in:
158
internal/service/plugin.go
Normal file
158
internal/service/plugin.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"xboard-go/internal/database"
|
||||
"xboard-go/internal/model"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
PluginRealNameVerification = "real_name_verification"
|
||||
PluginUserOnlineDevices = "user_online_devices"
|
||||
PluginUserAddIPv6 = "user_add_ipv6_subscription"
|
||||
)
|
||||
|
||||
func GetPlugin(code string) (*model.Plugin, bool) {
|
||||
var plugin model.Plugin
|
||||
if err := database.DB.Where("code = ?", code).First(&plugin).Error; err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return &plugin, true
|
||||
}
|
||||
|
||||
func IsPluginEnabled(code string) bool {
|
||||
plugin, ok := GetPlugin(code)
|
||||
return ok && plugin.IsEnabled
|
||||
}
|
||||
|
||||
func GetPluginConfig(code string) map[string]any {
|
||||
plugin, ok := GetPlugin(code)
|
||||
if !ok || plugin.Config == nil || *plugin.Config == "" {
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
var cfg map[string]any
|
||||
if err := json.Unmarshal([]byte(*plugin.Config), &cfg); err != nil {
|
||||
return map[string]any{}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func GetPluginConfigString(code, key, defaultValue string) string {
|
||||
cfg := GetPluginConfig(code)
|
||||
value, ok := cfg[key]
|
||||
if !ok {
|
||||
return defaultValue
|
||||
}
|
||||
if raw, ok := value.(string); ok && raw != "" {
|
||||
return raw
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func GetPluginConfigBool(code, key string, defaultValue bool) bool {
|
||||
cfg := GetPluginConfig(code)
|
||||
value, ok := cfg[key]
|
||||
if !ok {
|
||||
return defaultValue
|
||||
}
|
||||
switch typed := value.(type) {
|
||||
case bool:
|
||||
return typed
|
||||
case float64:
|
||||
return typed != 0
|
||||
case string:
|
||||
return typed == "1" || typed == "true"
|
||||
default:
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
func SyncIPv6ShadowAccount(user *model.User) bool {
|
||||
if user == nil || user.PlanID == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var plan model.Plan
|
||||
if err := database.DB.First(&plan, *user.PlanID).Error; err != nil {
|
||||
return false
|
||||
}
|
||||
if !PluginPlanAllowed(&plan) {
|
||||
return false
|
||||
}
|
||||
|
||||
ipv6Email := IPv6ShadowEmail(user.Email)
|
||||
var ipv6User model.User
|
||||
now := time.Now().Unix()
|
||||
if err := database.DB.Where("email = ?", ipv6Email).First(&ipv6User).Error; err != nil {
|
||||
ipv6User = *user
|
||||
ipv6User.ID = 0
|
||||
ipv6User.Email = ipv6Email
|
||||
ipv6User.UUID = uuid.New().String()
|
||||
ipv6User.Token = fmt.Sprintf("%x", md5.Sum([]byte(time.Now().String()+ipv6Email)))[:16]
|
||||
ipv6User.U = 0
|
||||
ipv6User.D = 0
|
||||
ipv6User.T = 0
|
||||
ipv6User.ParentID = &user.ID
|
||||
ipv6User.CreatedAt = now
|
||||
}
|
||||
|
||||
ipv6User.Email = ipv6Email
|
||||
ipv6User.Password = user.Password
|
||||
ipv6User.U = 0
|
||||
ipv6User.D = 0
|
||||
ipv6User.T = 0
|
||||
ipv6User.UpdatedAt = now
|
||||
|
||||
if planID := parsePluginPositiveInt(GetPluginConfigString(PluginUserAddIPv6, "ipv6_plan_id", "0"), 0); planID > 0 {
|
||||
ipv6User.PlanID = &planID
|
||||
}
|
||||
if groupID := parsePluginPositiveInt(GetPluginConfigString(PluginUserAddIPv6, "ipv6_group_id", "0"), 0); groupID > 0 {
|
||||
ipv6User.GroupID = &groupID
|
||||
}
|
||||
|
||||
return database.DB.Save(&ipv6User).Error == nil
|
||||
}
|
||||
|
||||
func PluginPlanAllowed(plan *model.Plan) bool {
|
||||
if plan == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, raw := range strings.Split(GetPluginConfigString(PluginUserAddIPv6, "allowed_plans", ""), ",") {
|
||||
if parsePluginPositiveInt(strings.TrimSpace(raw), 0) == plan.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
referenceFlag := strings.ToLower(GetPluginConfigString(PluginUserAddIPv6, "reference_flag", "ipv6"))
|
||||
reference := ""
|
||||
if plan.Reference != nil {
|
||||
reference = strings.ToLower(*plan.Reference)
|
||||
}
|
||||
return referenceFlag != "" && strings.Contains(reference, referenceFlag)
|
||||
}
|
||||
|
||||
func IPv6ShadowEmail(email string) string {
|
||||
suffix := GetPluginConfigString(PluginUserAddIPv6, "email_suffix", "-ipv6")
|
||||
parts := strings.SplitN(email, "@", 2)
|
||||
if len(parts) != 2 {
|
||||
return email
|
||||
}
|
||||
return parts[0] + suffix + "@" + parts[1]
|
||||
}
|
||||
|
||||
func parsePluginPositiveInt(raw string, defaultValue int) int {
|
||||
value, err := strconv.Atoi(strings.TrimSpace(raw))
|
||||
if err != nil || value <= 0 {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in New Issue
Block a user