initial commit: Go version of SMS Receiver with fixed template rendering
- Implemented all core features from Python version - Fixed int64/int type compatibility in template functions - Added login authentication, SMS receiving, statistics, logs - Independent database: sms_receiver_go.db - Fixed frontend display issues for message list and statistics
This commit is contained in:
142
config/config.go
Normal file
142
config/config.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
App AppConfig `mapstructure:"app"`
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Security SecurityConfig `mapstructure:"security"`
|
||||
SMS SMSConfig `mapstructure:"sms"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
Timezone string `mapstructure:"timezone"`
|
||||
APITokens []APIToken `mapstructure:"api_tokens"`
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Version string `mapstructure:"version"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Debug bool `mapstructure:"debug"`
|
||||
}
|
||||
|
||||
type SecurityConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
SessionLifetime int `mapstructure:"session_lifetime"`
|
||||
SecretKey string `mapstructure:"secret_key"`
|
||||
SignVerify bool `mapstructure:"sign_verify"`
|
||||
SignMaxAge int64 `mapstructure:"sign_max_age"`
|
||||
}
|
||||
|
||||
type SMSConfig struct {
|
||||
MaxMessages int `mapstructure:"max_messages"`
|
||||
AutoCleanup bool `mapstructure:"auto_cleanup"`
|
||||
CleanupDays int `mapstructure:"cleanup_days"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Path string `mapstructure:"path"`
|
||||
}
|
||||
|
||||
type APIToken struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Token string `mapstructure:"token"`
|
||||
Secret string `mapstructure:"secret"`
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
}
|
||||
|
||||
var cfg *Config
|
||||
|
||||
func Load(configPath string) (*Config, error) {
|
||||
viper.SetConfigFile(configPath)
|
||||
viper.SetConfigType("yaml")
|
||||
|
||||
// 允许环境变量覆盖
|
||||
viper.AutomaticEnv()
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("读取配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
cfg = &Config{}
|
||||
if err := viper.Unmarshal(cfg); err != nil {
|
||||
return nil, fmt.Errorf("解析配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func Get() *Config {
|
||||
return cfg
|
||||
}
|
||||
|
||||
// GetSessionLifetimeDuration 返回会话 lifetime 为 duration
|
||||
func (c *Config) GetSessionLifetimeDuration() time.Duration {
|
||||
return time.Duration(c.Security.SessionLifetime) * time.Second
|
||||
}
|
||||
|
||||
// GetSignMaxAgeDuration 返回签名最大有效期
|
||||
func (c *Config) GetSignMaxAgeDuration() time.Duration {
|
||||
return time.Duration(c.Security.SignMaxAge) * time.Millisecond
|
||||
}
|
||||
|
||||
// GetServerAddress 返回服务器地址
|
||||
func (c *Config) GetServerAddress() string {
|
||||
return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
|
||||
}
|
||||
|
||||
// GetTokenByName 根据名称获取 Token 配置
|
||||
func (c *Config) GetTokenByName(name string) *APIToken {
|
||||
for i := range c.APITokens {
|
||||
if c.APITokens[i].Name == name && c.APITokens[i].Enabled {
|
||||
return &c.APITokens[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTokenByValue 根据 token 值获取配置
|
||||
func (c *Config) GetTokenByValue(token string) *APIToken {
|
||||
for i := range c.APITokens {
|
||||
if c.APITokens[i].Token == token && c.APITokens[i].Enabled {
|
||||
return &c.APITokens[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save 保存配置到文件
|
||||
func (c *Config) Save(path string) error {
|
||||
viper.Set("app", c.App)
|
||||
viper.Set("server", c.Server)
|
||||
viper.Set("security", c.Security)
|
||||
viper.Set("sms", c.SMS)
|
||||
viper.Set("database", c.Database)
|
||||
viper.Set("timezone", c.Timezone)
|
||||
viper.Set("api_tokens", c.APITokens)
|
||||
|
||||
return viper.WriteConfigAs(path)
|
||||
}
|
||||
|
||||
// LoadDefault 加载默认配置文件
|
||||
func LoadDefault() (*Config, error) {
|
||||
configPath := "config.yaml"
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
// 尝试查找上层目录
|
||||
if _, err := os.Stat("../config.yaml"); err == nil {
|
||||
configPath = "../config.yaml"
|
||||
}
|
||||
}
|
||||
return Load(configPath)
|
||||
}
|
||||
Reference in New Issue
Block a user