refactor(updater): 重构 Go 版本更新器
- 更新项目名称为 AUTO_MAA_Go_Updater - 重构代码结构,优化函数命名和逻辑 - 移除 CDK 相关的冗余代码 - 调整版本号为 git commit hash - 更新构建配置和脚本 - 优化 API 客户端实现
This commit is contained in:
@@ -1,40 +1,38 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"AUTO_MAA_Go_Updater/assets"
|
||||
"gopkg.in/yaml.v3"
|
||||
"lightweight-updater/assets"
|
||||
)
|
||||
|
||||
// Config represents the application configuration
|
||||
// Config 表示应用程序配置
|
||||
type Config struct {
|
||||
ResourceID string `yaml:"resource_id"`
|
||||
CurrentVersion string `yaml:"current_version"`
|
||||
CDK string `yaml:"cdk,omitempty"`
|
||||
UserAgent string `yaml:"user_agent"`
|
||||
BackupURL string `yaml:"backup_url"`
|
||||
LogLevel string `yaml:"log_level"`
|
||||
AutoCheck bool `yaml:"auto_check"`
|
||||
CheckInterval int `yaml:"check_interval"` // seconds
|
||||
CheckInterval int `yaml:"check_interval"` // 秒
|
||||
}
|
||||
|
||||
// ConfigManager interface defines methods for configuration management
|
||||
// ConfigManager 定义配置管理的接口方法
|
||||
type ConfigManager interface {
|
||||
Load() (*Config, error)
|
||||
Save(config *Config) error
|
||||
GetConfigPath() string
|
||||
}
|
||||
|
||||
// DefaultConfigManager implements ConfigManager interface
|
||||
// DefaultConfigManager 实现 ConfigManager 接口
|
||||
type DefaultConfigManager struct {
|
||||
configPath string
|
||||
}
|
||||
|
||||
// NewConfigManager creates a new configuration manager
|
||||
// NewConfigManager 创建新的配置管理器
|
||||
func NewConfigManager() ConfigManager {
|
||||
configDir := getConfigDir()
|
||||
configPath := filepath.Join(configDir, "config.yaml")
|
||||
@@ -43,77 +41,77 @@ func NewConfigManager() ConfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfigPath returns the path to the configuration file
|
||||
// GetConfigPath 返回配置文件的路径
|
||||
func (cm *DefaultConfigManager) GetConfigPath() string {
|
||||
return cm.configPath
|
||||
}
|
||||
|
||||
// Load reads and parses the configuration file
|
||||
// Load 读取并解析配置文件
|
||||
func (cm *DefaultConfigManager) Load() (*Config, error) {
|
||||
// Create config directory if it doesn't exist
|
||||
// 如果配置目录不存在则创建
|
||||
configDir := filepath.Dir(cm.configPath)
|
||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create config directory: %w", err)
|
||||
return nil, fmt.Errorf("创建配置目录失败: %w", err)
|
||||
}
|
||||
|
||||
// If config file doesn't exist, create default config
|
||||
// 如果配置文件不存在,创建默认配置
|
||||
if _, err := os.Stat(cm.configPath); os.IsNotExist(err) {
|
||||
defaultConfig := getDefaultConfig()
|
||||
if err := cm.Save(defaultConfig); err != nil {
|
||||
return nil, fmt.Errorf("failed to create default config: %w", err)
|
||||
return nil, fmt.Errorf("创建默认配置失败: %w", err)
|
||||
}
|
||||
return defaultConfig, nil
|
||||
}
|
||||
|
||||
// Read existing config file
|
||||
// 读取现有配置文件
|
||||
data, err := os.ReadFile(cm.configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||
return nil, fmt.Errorf("读取配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
||||
return nil, fmt.Errorf("解析配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
// Validate and apply defaults for missing fields
|
||||
// 验证并应用缺失字段的默认值
|
||||
if err := validateAndApplyDefaults(&config); err != nil {
|
||||
return nil, fmt.Errorf("config validation failed: %w", err)
|
||||
return nil, fmt.Errorf("配置验证失败: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// Save writes the configuration to file
|
||||
// Save 将配置写入文件
|
||||
func (cm *DefaultConfigManager) Save(config *Config) error {
|
||||
// Validate config before saving
|
||||
// 保存前验证配置
|
||||
if err := validateConfig(config); err != nil {
|
||||
return fmt.Errorf("config validation failed: %w", err)
|
||||
return fmt.Errorf("配置验证失败: %w", err)
|
||||
}
|
||||
|
||||
// Create config directory if it doesn't exist
|
||||
// 如果配置目录不存在则创建
|
||||
configDir := filepath.Dir(cm.configPath)
|
||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create config directory: %w", err)
|
||||
return fmt.Errorf("创建配置目录失败: %w", err)
|
||||
}
|
||||
|
||||
// Marshal config to YAML
|
||||
// 将配置序列化为 YAML
|
||||
data, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %w", err)
|
||||
return fmt.Errorf("序列化配置失败: %w", err)
|
||||
}
|
||||
|
||||
// Write to file
|
||||
// 写入文件
|
||||
if err := os.WriteFile(cm.configPath, data, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write config file: %w", err)
|
||||
return fmt.Errorf("写入配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDefaultConfig returns a configuration with default values
|
||||
// getDefaultConfig 返回带有默认值的配置
|
||||
func getDefaultConfig() *Config {
|
||||
// Try to load from embedded template first
|
||||
// 首先尝试从嵌入模板加载
|
||||
if templateData, err := assets.GetConfigTemplate(); err == nil {
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(templateData, &config); err == nil {
|
||||
@@ -121,35 +119,34 @@ func getDefaultConfig() *Config {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to hardcoded defaults if template loading fails
|
||||
// 如果模板加载失败则回退到硬编码默认值
|
||||
return &Config{
|
||||
ResourceID: "M9A", // Default resource ID
|
||||
ResourceID: "M9A", // 默认资源 ID
|
||||
CurrentVersion: "v1.0.0",
|
||||
CDK: "",
|
||||
UserAgent: "LightweightUpdater/1.0",
|
||||
UserAgent: "AUTO_MAA_Go_Updater/1.0",
|
||||
BackupURL: "",
|
||||
LogLevel: "info",
|
||||
AutoCheck: true,
|
||||
CheckInterval: 3600, // 1 hour
|
||||
CheckInterval: 3600, // 1 小时
|
||||
}
|
||||
}
|
||||
|
||||
// validateConfig validates the configuration values
|
||||
// validateConfig 验证配置值
|
||||
func validateConfig(config *Config) error {
|
||||
if config == nil {
|
||||
return fmt.Errorf("config cannot be nil")
|
||||
return fmt.Errorf("配置不能为空")
|
||||
}
|
||||
|
||||
if config.ResourceID == "" {
|
||||
return fmt.Errorf("resource_id cannot be empty")
|
||||
return fmt.Errorf("resource_id 不能为空")
|
||||
}
|
||||
|
||||
if config.CurrentVersion == "" {
|
||||
return fmt.Errorf("current_version cannot be empty")
|
||||
return fmt.Errorf("current_version 不能为空")
|
||||
}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
return fmt.Errorf("user_agent cannot be empty")
|
||||
return fmt.Errorf("user_agent 不能为空")
|
||||
}
|
||||
|
||||
validLogLevels := map[string]bool{
|
||||
@@ -159,21 +156,21 @@ func validateConfig(config *Config) error {
|
||||
"error": true,
|
||||
}
|
||||
if !validLogLevels[config.LogLevel] {
|
||||
return fmt.Errorf("invalid log_level: %s (must be debug, info, warn, or error)", config.LogLevel)
|
||||
return fmt.Errorf("无效的 log_level: %s (必须是 debug, info, warn 或 error)", config.LogLevel)
|
||||
}
|
||||
|
||||
if config.CheckInterval < 60 {
|
||||
return fmt.Errorf("check_interval must be at least 60 seconds")
|
||||
return fmt.Errorf("check_interval 必须至少为 60 秒")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateAndApplyDefaults validates config and applies defaults for missing fields
|
||||
// validateAndApplyDefaults 验证配置并为缺失字段应用默认值
|
||||
func validateAndApplyDefaults(config *Config) error {
|
||||
defaults := getDefaultConfig()
|
||||
|
||||
// Apply defaults for empty fields
|
||||
// 为空字段应用默认值
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = defaults.UserAgent
|
||||
}
|
||||
@@ -187,62 +184,15 @@ func validateAndApplyDefaults(config *Config) error {
|
||||
config.CurrentVersion = defaults.CurrentVersion
|
||||
}
|
||||
|
||||
// Validate after applying defaults
|
||||
// 应用默认值后进行验证
|
||||
return validateConfig(config)
|
||||
}
|
||||
|
||||
// getConfigDir returns the configuration directory path
|
||||
// getConfigDir 返回配置目录路径
|
||||
func getConfigDir() string {
|
||||
// Use APPDATA on Windows, fallback to current directory
|
||||
// 在 Windows 上使用 APPDATA,回退到当前目录
|
||||
if appData := os.Getenv("APPDATA"); appData != "" {
|
||||
return filepath.Join(appData, "LightweightUpdater")
|
||||
return filepath.Join(appData, "AUTO_MAA_Go_Updater")
|
||||
}
|
||||
return "."
|
||||
}
|
||||
|
||||
// encryptCDK encrypts the CDK using XOR encryption with a static key
|
||||
func encryptCDK(cdk string) string {
|
||||
if cdk == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
key := []byte("updater-key-2024")
|
||||
encrypted := make([]byte, len(cdk))
|
||||
|
||||
for i, b := range []byte(cdk) {
|
||||
encrypted[i] = b ^ key[i%len(key)]
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(encrypted)
|
||||
}
|
||||
|
||||
// decryptCDK decrypts the CDK using XOR decryption with a static key
|
||||
func decryptCDK(encryptedCDK string) (string, error) {
|
||||
if encryptedCDK == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
encrypted, err := base64.StdEncoding.DecodeString(encryptedCDK)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode encrypted CDK: %w", err)
|
||||
}
|
||||
|
||||
key := []byte("updater-key-2024")
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
|
||||
for i, b := range encrypted {
|
||||
decrypted[i] = b ^ key[i%len(key)]
|
||||
}
|
||||
|
||||
return string(decrypted), nil
|
||||
}
|
||||
|
||||
// SetCDK sets the CDK in the config with encryption
|
||||
func (c *Config) SetCDK(cdk string) {
|
||||
c.CDK = encryptCDK(cdk)
|
||||
}
|
||||
|
||||
// GetCDK returns the decrypted CDK from the config
|
||||
func (c *Config) GetCDK() (string, error) {
|
||||
return decryptCDK(c.CDK)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user