Files
SaveAny-Bot/config/viper.go

149 lines
4.2 KiB
Go

package config
import (
"context"
"errors"
"fmt"
"strings"
"github.com/duke-git/lancet/v2/slice"
"github.com/krau/SaveAny-Bot/common/i18n"
"github.com/krau/SaveAny-Bot/common/i18n/i18nk"
"github.com/krau/SaveAny-Bot/config/storage"
"github.com/spf13/viper"
)
type Config struct {
Lang string `toml:"lang" mapstructure:"lang" json:"lang"`
Workers int `toml:"workers" mapstructure:"workers"`
Retry int `toml:"retry" mapstructure:"retry"`
NoCleanCache bool `toml:"no_clean_cache" mapstructure:"no_clean_cache" json:"no_clean_cache"`
Threads int `toml:"threads" mapstructure:"threads" json:"threads"`
Stream bool `toml:"stream" mapstructure:"stream" json:"stream"`
Cache cacheConfig `toml:"cache" mapstructure:"cache" json:"cache"`
Users []userConfig `toml:"users" mapstructure:"users" json:"users"`
Temp tempConfig `toml:"temp" mapstructure:"temp"`
DB dbConfig `toml:"db" mapstructure:"db"`
Telegram telegramConfig `toml:"telegram" mapstructure:"telegram"`
Storages []storage.StorageConfig `toml:"-" mapstructure:"-" json:"storages"`
Parser parserConfig `toml:"parser" mapstructure:"parser" json:"parser"`
Hook hookConfig `toml:"hook" mapstructure:"hook" json:"hook"`
}
var cfg = &Config{}
func C() Config {
return *cfg
}
func (c Config) GetStorageByName(name string) storage.StorageConfig {
for _, storage := range c.Storages {
if storage.GetName() == name {
return storage
}
}
return nil
}
func Init(ctx context.Context) error {
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.AddConfigPath("/etc/saveany/")
viper.SetConfigType("toml")
viper.SetEnvPrefix("SAVEANY")
viper.AutomaticEnv()
replacer := strings.NewReplacer(".", "_")
viper.SetEnvKeyReplacer(replacer)
defaultConfigs := map[string]any{
// 基础配置
"lang": "zh-Hans",
"workers": 3,
"retry": 3,
"threads": 4,
// 缓存配置
"cache.ttl": 86400,
"cache.num_counters": 1e5,
"cache.max_cost": 1e6,
// Telegram
"telegram.app_id": 1025907,
"telegram.app_hash": "452b0359b988148995f22ff0f4229750",
"telegram.rpc_retry": 5,
"telegram.userbot.enable": false,
"telegram.userbot.session": "data/usersession.db",
// 临时目录
"temp.base_path": "cache/",
// 数据库
"db.path": "data/saveany.db",
"db.session": "data/session.db",
}
for key, value := range defaultConfigs {
viper.SetDefault(key, value)
}
if err := viper.SafeWriteConfigAs("config.toml"); err != nil {
if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {
return fmt.Errorf("error saving default config: %w", err)
}
}
if err := viper.ReadInConfig(); err != nil {
fmt.Println("Error reading config file, ", err)
return err
}
if err := viper.Unmarshal(cfg); err != nil {
fmt.Println("Error unmarshalling config file, ", err)
return err
}
storagesConfig, err := storage.LoadStorageConfigs(viper.GetViper())
if err != nil {
return fmt.Errorf("error loading storage configs: %w", err)
}
cfg.Storages = storagesConfig
storageNames := make(map[string]struct{})
for _, storage := range cfg.Storages {
if _, ok := storageNames[storage.GetName()]; ok {
return errors.New(i18n.TWithoutInit(cfg.Lang, i18nk.ConfigInvalidDuplicateStorageName, map[string]any{
"Name": storage.GetName(),
}))
}
storageNames[storage.GetName()] = struct{}{}
}
fmt.Println(i18n.TWithoutInit(cfg.Lang, i18nk.LoadedStorages, map[string]any{
"Count": len(cfg.Storages),
}))
for _, storage := range cfg.Storages {
fmt.Printf(" - %s (%s)\n", storage.GetName(), storage.GetType())
}
if cfg.Workers < 1 || cfg.Retry < 1 {
return errors.New(i18n.TWithoutInit(cfg.Lang, i18nk.ConfigInvalidWorkersOrRetry, map[string]any{
"Workers": cfg.Workers,
"Retry": cfg.Retry,
}))
}
for _, storage := range cfg.Storages {
storages = append(storages, storage.GetName())
}
for _, user := range cfg.Users {
userIDs = append(userIDs, user.ID)
if user.Blacklist {
userStorages[user.ID] = slice.Compact(slice.Difference(storages, user.Storages))
} else {
userStorages[user.ID] = user.Storages
}
}
return nil
}