146 lines
3.3 KiB
Go
146 lines
3.3 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Config 应用配置
|
|
type Config struct {
|
|
DatabaseURL string
|
|
ListenAddr string
|
|
APIKey string
|
|
ReturnSecret bool
|
|
MaxConcurrency int
|
|
MaxTestLimit int
|
|
LeaseTTL time.Duration
|
|
|
|
// Telegram Bot 配置
|
|
TelegramBotToken string
|
|
TelegramAdminIDs []int64
|
|
TelegramNotifyChatID string
|
|
TelegramTestIntervalMin int
|
|
TelegramAlertThreshold int
|
|
TelegramTestURL string
|
|
TelegramTestTimeoutMs int
|
|
}
|
|
|
|
// Load 从环境变量加载配置
|
|
func Load() *Config {
|
|
cfg := &Config{
|
|
DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/proxyrotator?sslmode=disable"),
|
|
ListenAddr: getEnv("LISTEN_ADDR", ":8080"),
|
|
APIKey: getEnv("API_KEY", ""),
|
|
ReturnSecret: getEnvBool("RETURN_SECRET", true),
|
|
MaxConcurrency: getEnvInt("MAX_CONCURRENCY", 200),
|
|
MaxTestLimit: getEnvInt("MAX_TEST_LIMIT", 2000),
|
|
LeaseTTL: getEnvDuration("LEASE_TTL", 60*time.Second),
|
|
|
|
// Telegram
|
|
TelegramBotToken: getEnv("TELEGRAM_BOT_TOKEN", ""),
|
|
TelegramAdminIDs: getEnvInt64Slice("TELEGRAM_ADMIN_IDS", nil),
|
|
TelegramNotifyChatID: getEnv("TELEGRAM_NOTIFY_CHAT_ID", ""),
|
|
TelegramTestIntervalMin: getEnvInt("TELEGRAM_TEST_INTERVAL_MIN", 60),
|
|
TelegramAlertThreshold: getEnvInt("TELEGRAM_ALERT_THRESHOLD", 50),
|
|
TelegramTestURL: getEnv("TELEGRAM_TEST_URL", "https://httpbin.org/ip"),
|
|
TelegramTestTimeoutMs: getEnvInt("TELEGRAM_TEST_TIMEOUT_MS", 5000),
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvBool(key string, defaultValue bool) bool {
|
|
if v := os.Getenv(key); v != "" {
|
|
b, err := strconv.ParseBool(v)
|
|
if err == nil {
|
|
return b
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvInt(key string, defaultValue int) int {
|
|
if v := os.Getenv(key); v != "" {
|
|
i, err := strconv.Atoi(v)
|
|
if err == nil {
|
|
return i
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvDuration(key string, defaultValue time.Duration) time.Duration {
|
|
if v := os.Getenv(key); v != "" {
|
|
d, err := time.ParseDuration(v)
|
|
if err == nil {
|
|
return d
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvInt64Slice(key string, defaultValue []int64) []int64 {
|
|
v := os.Getenv(key)
|
|
if v == "" {
|
|
return defaultValue
|
|
}
|
|
parts := splitAndTrim(v, ",")
|
|
result := make([]int64, 0, len(parts))
|
|
for _, p := range parts {
|
|
if p == "" {
|
|
continue
|
|
}
|
|
i, err := strconv.ParseInt(p, 10, 64)
|
|
if err == nil {
|
|
result = append(result, i)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func splitAndTrim(s, sep string) []string {
|
|
parts := make([]string, 0)
|
|
for _, p := range stringsSplit(s, sep) {
|
|
p = stringsTrim(p)
|
|
if p != "" {
|
|
parts = append(parts, p)
|
|
}
|
|
}
|
|
return parts
|
|
}
|
|
|
|
func stringsSplit(s, sep string) []string {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
result := make([]string, 0)
|
|
start := 0
|
|
for i := 0; i < len(s); i++ {
|
|
if i+len(sep) <= len(s) && s[i:i+len(sep)] == sep {
|
|
result = append(result, s[start:i])
|
|
start = i + len(sep)
|
|
i += len(sep) - 1
|
|
}
|
|
}
|
|
result = append(result, s[start:])
|
|
return result
|
|
}
|
|
|
|
func stringsTrim(s string) string {
|
|
start, end := 0, len(s)
|
|
for start < end && (s[start] == ' ' || s[start] == '\t') {
|
|
start++
|
|
}
|
|
for end > start && (s[end-1] == ' ' || s[end-1] == '\t') {
|
|
end--
|
|
}
|
|
return s[start:end]
|
|
}
|