Initial GoWallpaper implementation
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const configFileName = "config.json"
|
||||
|
||||
type Config struct {
|
||||
APIURL string `json:"api_url"`
|
||||
AutoChangeEnabled bool `json:"auto_change_enabled"`
|
||||
IntervalMinutes int `json:"interval_minutes"`
|
||||
MaxCacheCount int `json:"max_cache_count"`
|
||||
WallpaperStyle string `json:"wallpaper_style"`
|
||||
StartWithWindows bool `json:"start_with_windows"`
|
||||
}
|
||||
|
||||
func defaultConfig() Config {
|
||||
return Config{
|
||||
IntervalMinutes: 30,
|
||||
MaxCacheCount: 10,
|
||||
WallpaperStyle: "keep",
|
||||
}
|
||||
}
|
||||
|
||||
func loadOrCreateConfig(path string) (Config, bool, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
cfg := defaultConfig()
|
||||
if err := saveConfig(path, cfg); err != nil {
|
||||
return Config{}, false, err
|
||||
}
|
||||
return cfg, true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return Config{}, false, fmt.Errorf("读取配置文件: %w", err)
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := json.Unmarshal(data, &cfg); err != nil {
|
||||
return Config{}, false, fmt.Errorf("解析配置文件: %w", err)
|
||||
}
|
||||
if err := cfg.validate(false); err != nil {
|
||||
return Config{}, false, fmt.Errorf("配置文件无效: %w", err)
|
||||
}
|
||||
return cfg, false, nil
|
||||
}
|
||||
|
||||
func saveConfig(path string, cfg Config) error {
|
||||
if err := cfg.validate(false); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("编码配置文件: %w", err)
|
||||
}
|
||||
data = append(data, '\n')
|
||||
if err := atomicWriteFile(path, data, 0o644); err != nil {
|
||||
return fmt.Errorf("保存配置文件: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Config) validate(requireURL bool) error {
|
||||
if c.IntervalMinutes <= 0 {
|
||||
return errors.New("自动切换间隔必须大于 0 分钟")
|
||||
}
|
||||
if c.MaxCacheCount <= 0 {
|
||||
return errors.New("缓存数量必须大于 0")
|
||||
}
|
||||
if requireURL && c.APIURL == "" {
|
||||
return errors.New("请先设置随机图片 API 地址")
|
||||
}
|
||||
if c.APIURL != "" {
|
||||
u, err := url.ParseRequestURI(c.APIURL)
|
||||
if err != nil || u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
|
||||
return errors.New("API 地址必须是有效的 HTTP 或 HTTPS 地址")
|
||||
}
|
||||
}
|
||||
if !validWallpaperStyle(c.WallpaperStyle) {
|
||||
return errors.New("不支持的壁纸显示方式")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func atomicWriteFile(path string, data []byte, perm os.FileMode) error {
|
||||
dir := filepath.Dir(path)
|
||||
tmp, err := os.CreateTemp(dir, ".gowallpaper-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpName := tmp.Name()
|
||||
defer os.Remove(tmpName)
|
||||
|
||||
if err := tmp.Chmod(perm); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if _, err := tmp.Write(data); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if err := tmp.Sync(); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
if err := tmp.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(path); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpName, path)
|
||||
}
|
||||
Reference in New Issue
Block a user