185 lines
7.2 KiB
Go
185 lines
7.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"xboard-go/internal/database"
|
|
"xboard-go/internal/model"
|
|
"xboard-go/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AdminConfigFetch returns modular configuration settings based on Categories.
|
|
// This matches the official Xboard ConfigController.fetch logic.
|
|
func AdminConfigFetch(c *gin.Context) {
|
|
key := c.Query("key")
|
|
mappings := getAllConfigMappings()
|
|
|
|
if key != "" {
|
|
if val, ok := mappings[key]; ok {
|
|
Success(c, gin.H{key: val})
|
|
return
|
|
}
|
|
}
|
|
|
|
Success(c, mappings)
|
|
}
|
|
|
|
// AdminConfigSave saves configuration settings.
|
|
func AdminConfigSave(c *gin.Context) {
|
|
var payload map[string]any
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
Fail(c, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
|
|
// In a real implementation, we'd loop through payload and update model.Setting
|
|
// We also handle special keys like subscribe_template_* or frontend_theme
|
|
for k, v := range payload {
|
|
// Special handling for templates could go here
|
|
saveSetting(k, v)
|
|
}
|
|
|
|
Success(c, true)
|
|
}
|
|
|
|
// AdminGetEmailTemplate list available email templates.
|
|
func AdminGetEmailTemplate(c *gin.Context) {
|
|
path := filepath.Join("resource", "views", "mail")
|
|
files, err := listFiles(path, "*")
|
|
if err != nil {
|
|
Success(c, []string{})
|
|
return
|
|
}
|
|
Success(c, files)
|
|
}
|
|
|
|
// AdminGetThemeTemplate list available themes.
|
|
func AdminGetThemeTemplate(c *gin.Context) {
|
|
path := filepath.Join("public", "theme")
|
|
files, err := listFiles(path, "*")
|
|
if err != nil {
|
|
Success(c, []string{})
|
|
return
|
|
}
|
|
Success(c, files)
|
|
}
|
|
|
|
func getAllConfigMappings() gin.H {
|
|
return gin.H{
|
|
"invite": gin.H{
|
|
"invite_force": service.MustGetBool("invite_force", false),
|
|
"invite_commission": service.MustGetInt("invite_commission", 10),
|
|
"invite_gen_limit": service.MustGetInt("invite_gen_limit", 5),
|
|
"invite_never_expire": service.MustGetBool("invite_never_expire", false),
|
|
"commission_first_time_enable": service.MustGetBool("commission_first_time_enable", true),
|
|
"commission_auto_check_enable": service.MustGetBool("commission_auto_check_enable", true),
|
|
"commission_withdraw_limit": service.MustGetInt("commission_withdraw_limit", 100),
|
|
"commission_withdraw_method": service.MustGetString("commission_withdraw_method", "alipay"),
|
|
"withdraw_close_enable": service.MustGetBool("withdraw_close_enable", false),
|
|
"commission_distribution_enable": service.MustGetBool("commission_distribution_enable", false),
|
|
"commission_distribution_l1": service.MustGetInt("commission_distribution_l1", 0),
|
|
"commission_distribution_l2": service.MustGetInt("commission_distribution_l2", 0),
|
|
"commission_distribution_l3": service.MustGetInt("commission_distribution_l3", 0),
|
|
},
|
|
"site": gin.H{
|
|
"logo": service.MustGetString("logo", ""),
|
|
"force_https": service.MustGetInt("force_https", 0),
|
|
"stop_register": service.MustGetInt("stop_register", 0),
|
|
"app_name": service.MustGetString("app_name", "XBoard"),
|
|
"app_description": service.MustGetString("app_description", "XBoard is best!"),
|
|
"app_url": service.MustGetString("app_url", ""),
|
|
"subscribe_url": service.MustGetString("subscribe_url", ""),
|
|
"try_out_plan_id": service.MustGetInt("try_out_plan_id", 0),
|
|
"try_out_hour": service.MustGetInt("try_out_hour", 1),
|
|
"tos_url": service.MustGetString("tos_url", ""),
|
|
"currency": service.MustGetString("currency", "CNY"),
|
|
"currency_symbol": service.MustGetString("currency_symbol", "¥"),
|
|
"ticket_must_wait_reply": service.MustGetBool("ticket_must_wait_reply", false),
|
|
},
|
|
"subscribe": gin.H{
|
|
"plan_change_enable": service.MustGetBool("plan_change_enable", true),
|
|
"reset_traffic_method": service.MustGetInt("reset_traffic_method", 0),
|
|
"surplus_enable": service.MustGetBool("surplus_enable", true),
|
|
"new_order_event_id": service.MustGetInt("new_order_event_id", 0),
|
|
"renew_order_event_id": service.MustGetInt("renew_order_event_id", 0),
|
|
"change_order_event_id": service.MustGetInt("change_order_event_id", 0),
|
|
"show_info_to_server_enable": service.MustGetBool("show_info_to_server_enable", false),
|
|
"show_protocol_to_server_enable": service.MustGetBool("show_protocol_to_server_enable", false),
|
|
"default_remind_expire": service.MustGetBool("default_remind_expire", true),
|
|
"default_remind_traffic" : service.MustGetBool("default_remind_traffic", true),
|
|
"subscribe_path": service.MustGetString("subscribe_path", "s"),
|
|
},
|
|
"frontend": gin.H{
|
|
"frontend_theme": service.MustGetString("frontend_theme", "Xboard"),
|
|
"frontend_theme_sidebar": service.MustGetString("frontend_theme_sidebar", "light"),
|
|
"frontend_theme_header": service.MustGetString("frontend_theme_header", "dark"),
|
|
"frontend_theme_color": service.MustGetString("frontend_theme_color", "default"),
|
|
"frontend_background_url": service.MustGetString("frontend_background_url", ""),
|
|
},
|
|
"server": gin.H{
|
|
"server_token": service.MustGetString("server_token", ""),
|
|
"server_pull_interval": service.MustGetInt("server_pull_interval", 60),
|
|
"server_push_interval": service.MustGetInt("server_push_interval", 60),
|
|
"device_limit_mode": service.MustGetInt("device_limit_mode", 0),
|
|
"server_ws_enable": service.MustGetBool("server_ws_enable", true),
|
|
"server_ws_url": service.MustGetString("server_ws_url", ""),
|
|
},
|
|
"safe": gin.H{
|
|
"email_verify": service.MustGetBool("email_verify", false),
|
|
"safe_mode_enable": service.MustGetBool("safe_mode_enable", false),
|
|
"secure_path": service.GetAdminSecurePath(),
|
|
"email_whitelist_enable": service.MustGetBool("email_whitelist_enable", false),
|
|
"email_whitelist_suffix": service.MustGetString("email_whitelist_suffix", ""),
|
|
"email_gmail_limit_enable": service.MustGetBool("email_gmail_limit_enable", false),
|
|
"captcha_enable": service.MustGetBool("captcha_enable", false),
|
|
"captcha_type": service.MustGetString("captcha_type", "recaptcha"),
|
|
"register_limit_by_ip_enable": service.MustGetBool("register_limit_by_ip_enable", false),
|
|
"register_limit_count": service.MustGetInt("register_limit_count", 3),
|
|
"password_limit_enable": service.MustGetBool("password_limit_enable", true),
|
|
},
|
|
}
|
|
}
|
|
|
|
func saveSetting(name string, value any) {
|
|
var val string
|
|
switch v := value.(type) {
|
|
case string:
|
|
val = v
|
|
case int:
|
|
val = strconv.Itoa(v)
|
|
case int64:
|
|
val = strconv.FormatInt(v, 10)
|
|
case float64:
|
|
val = fmt.Sprintf("%f", v)
|
|
case bool:
|
|
if v {
|
|
val = "1"
|
|
} else {
|
|
val = "0"
|
|
}
|
|
default:
|
|
// serialize complex types if needed
|
|
}
|
|
|
|
database.DB.Model(&model.Setting{}).Where("name = ?", name).Update("value", val)
|
|
}
|
|
|
|
func listFiles(dir string, pattern string) ([]string, error) {
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var files []string
|
|
for _, entry := range entries {
|
|
if !entry.IsDir() {
|
|
files = append(files, entry.Name())
|
|
}
|
|
}
|
|
return files, nil
|
|
}
|