go-bot/config/config.go

152 lines
3.1 KiB
Go

package config
import (
"fmt"
"os"
"reflect"
"sync"
"time"
"github.com/BurntSushi/toml"
"github.com/fsnotify/fsnotify"
"github.com/sirupsen/logrus"
)
var (
config map[string]interface{}
mu sync.RWMutex
)
// loadConfig 加载配置文件
func loadConfig() error {
// mu.Lock()
// defer mu.Unlock()
_, err := toml.DecodeFile("config.toml", &config)
if err != nil {
logrus.Errorf("Failed to decode config file: %v", err)
}
return err
}
// GetConfig 获取配置
func GetConfig() map[string]interface{} {
// mu.RLock()
if err := loadConfig(); err != nil {
fmt.Printf("加载配置文件失败: %v\n", err)
os.Exit(1)
}
return config
}
// ReloadConfig 重新加载配置文件
func ReloadConfig() error {
mu.Lock()
defer mu.Unlock()
if err := loadConfig(); err != nil {
logrus.Errorf("failed to reload config: %v", err)
return err
}
logrus.Infof("Config reloaded successfully:%v", config)
return nil
}
// GetConfigValue 获取配置值
func GetConfigValue(key string) interface{} {
mu.RLock()
defer mu.RUnlock()
return config[key]
}
// ModifyConfig 修改配置并写回文件
func ModifyConfig(key string, value interface{}) error {
mu.Lock()
defer mu.Unlock()
config[key] = value
file, err := os.Create("config.toml")
if err != nil {
return err
}
defer file.Close()
encoder := toml.NewEncoder(file)
return encoder.Encode(config)
}
// PrintConfig 递归打印配置内容
func PrintConfig(m map[string]interface{}, indent string) {
for key, value := range m {
switch v := value.(type) {
case map[string]interface{}:
fmt.Printf("%s%s (type: %s):\n", indent, key, reflect.TypeOf(v))
PrintConfig(v, indent+" ")
case []interface{}:
fmt.Printf("%s%s:\n", indent, key)
for i, item := range v {
switch itemValue := item.(type) {
case map[string]interface{}:
fmt.Printf("%s [%d] (type: %s):\n", indent, i, reflect.TypeOf(itemValue))
PrintConfig(itemValue, indent+" ")
default:
fmt.Printf("%s [%d] (type: %s): %v\n", indent, i, reflect.TypeOf(itemValue), item)
}
}
default:
fmt.Printf("%s%s (type: %s): %v\n", indent, key, reflect.TypeOf(value), value)
}
}
}
// 监听配置文件变化
func WatchConfig(filepath string) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
logrus.Fatalf("Failed to create watcher: %v", err)
}
defer watcher.Close()
err = watcher.Add(filepath)
if err != nil {
logrus.Fatalf("Failed to add file to watcher: %v", err)
}
var debounceTimer *time.Timer
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op&(fsnotify.Write|fsnotify.Rename) != 0 {
if debounceTimer != nil {
debounceTimer.Stop()
}
debounceTimer = time.AfterFunc(500*time.Millisecond, func() {
logrus.Info("Config file changed, reloading...")
go func() {
if err := ReloadConfig(); err != nil {
logrus.Errorf("Failed to reload config: %v", err)
}
}()
})
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
logrus.Errorf("Watcher error: %v", err)
}
}
}
// 启动监听配置文件的协程
func StartWatching(filepath string) {
go WatchConfig(filepath)
}