feat: refactor storage configuration to use dedicated storage package and add new storage types
BREAKING CHANGE: remove deprecated config
This commit is contained in:
@@ -1,95 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// for compatibility
|
||||
type deprecatedStorageConfig struct {
|
||||
Alist alistConfig `toml:"alist" mapstructure:"alist"`
|
||||
Local localConfig `toml:"local" mapstructure:"local"`
|
||||
Webdav webdavConfig `toml:"webdav" mapstructure:"webdav"`
|
||||
}
|
||||
|
||||
type alistConfig struct {
|
||||
Enable bool `toml:"enable" mapstructure:"enable" json:"enable"`
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
Token string `toml:"token" mapstructure:"token" json:"token"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
TokenExp int64 `toml:"token_exp" mapstructure:"token_exp" json:"token_exp"`
|
||||
}
|
||||
|
||||
func (a *alistConfig) ToJSON() datatypes.JSON {
|
||||
tokenExp := strconv.FormatInt(a.TokenExp, 10)
|
||||
return datatypes.JSON([]byte(`{"url":"` + a.URL + `","username":"` + a.Username + `","password":"` + a.Password + `","token":"` + a.Token + `","base_path":"` + a.BasePath + `","token_exp":` + tokenExp + `}`))
|
||||
}
|
||||
|
||||
type localConfig struct {
|
||||
Enable bool `toml:"enable" mapstructure:"enable" json:"enable"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (l *localConfig) ToJSON() datatypes.JSON {
|
||||
return datatypes.JSON([]byte(`{"base_path":"` + l.BasePath + `"}`))
|
||||
}
|
||||
|
||||
type webdavConfig struct {
|
||||
Enable bool `toml:"enable" mapstructure:"enable" json:"enable"`
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (w *webdavConfig) ToJSON() datatypes.JSON {
|
||||
return datatypes.JSON([]byte(`{"url":"` + w.URL + `","username":"` + w.Username + `","password":"` + w.Password + `","base_path":"` + w.BasePath + `"}`))
|
||||
}
|
||||
|
||||
func transformDeprecatedStorageConfig() {
|
||||
if Cfg.DeprecatedStorage.Alist.Enable {
|
||||
alistStorage := &AlistStorageConfig{
|
||||
NewStorageConfig: NewStorageConfig{
|
||||
Name: "Alist",
|
||||
Enable: true,
|
||||
Type: string(types.StorageTypeAlist),
|
||||
},
|
||||
URL: Cfg.DeprecatedStorage.Alist.URL,
|
||||
Username: Cfg.DeprecatedStorage.Alist.Username,
|
||||
Password: Cfg.DeprecatedStorage.Alist.Password,
|
||||
Token: Cfg.DeprecatedStorage.Alist.Token,
|
||||
BasePath: Cfg.DeprecatedStorage.Alist.BasePath,
|
||||
TokenExp: Cfg.DeprecatedStorage.Alist.TokenExp,
|
||||
}
|
||||
Cfg.Storages = append(Cfg.Storages, alistStorage)
|
||||
}
|
||||
if Cfg.DeprecatedStorage.Local.Enable {
|
||||
localStorage := &LocalStorageConfig{
|
||||
NewStorageConfig: NewStorageConfig{
|
||||
Name: "Local",
|
||||
Enable: true,
|
||||
Type: string(types.StorageTypeLocal),
|
||||
},
|
||||
BasePath: Cfg.DeprecatedStorage.Local.BasePath,
|
||||
}
|
||||
Cfg.Storages = append(Cfg.Storages, localStorage)
|
||||
}
|
||||
if Cfg.DeprecatedStorage.Webdav.Enable {
|
||||
webdavStorage := &WebdavStorageConfig{
|
||||
NewStorageConfig: NewStorageConfig{
|
||||
Name: "Webdav",
|
||||
Enable: true,
|
||||
Type: string(types.StorageTypeWebdav),
|
||||
},
|
||||
URL: Cfg.DeprecatedStorage.Webdav.URL,
|
||||
Username: Cfg.DeprecatedStorage.Webdav.Username,
|
||||
Password: Cfg.DeprecatedStorage.Webdav.Password,
|
||||
BasePath: Cfg.DeprecatedStorage.Webdav.BasePath,
|
||||
}
|
||||
Cfg.Storages = append(Cfg.Storages, webdavStorage)
|
||||
}
|
||||
}
|
||||
38
config/storage/alist.go
Normal file
38
config/storage/alist.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
type AlistStorageConfig struct {
|
||||
BaseConfig
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
Token string `toml:"token" mapstructure:"token" json:"token"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
TokenExp int64 `toml:"token_exp" mapstructure:"token_exp" json:"token_exp"`
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) Validate() error {
|
||||
if a.URL == "" {
|
||||
return fmt.Errorf("url is required for alist storage")
|
||||
}
|
||||
if a.Token == "" && (a.Username == "" || a.Password == "") {
|
||||
return fmt.Errorf("username and password or token is required for alist storage")
|
||||
}
|
||||
if a.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for alist storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeAlist
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) GetName() string {
|
||||
return a.Name
|
||||
}
|
||||
63
config/storage/factory.go
Normal file
63
config/storage/factory.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var storageFactories = map[types.StorageType]func(cfg *BaseConfig) (StorageConfig, error){
|
||||
types.StorageTypeLocal: createStorageConfig(&LocalStorageConfig{}),
|
||||
types.StorageTypeAlist: createStorageConfig(&AlistStorageConfig{}),
|
||||
types.StorageTypeWebdav: createStorageConfig(&WebdavStorageConfig{}),
|
||||
types.StorageTypeMinio: createStorageConfig(&MinioStorageConfig{}),
|
||||
}
|
||||
|
||||
func createStorageConfig(configType StorageConfig) func(cfg *BaseConfig) (StorageConfig, error) {
|
||||
return func(cfg *BaseConfig) (StorageConfig, error) {
|
||||
configValue := reflect.New(reflect.TypeOf(configType).Elem()).Interface().(StorageConfig)
|
||||
|
||||
reflect.ValueOf(configValue).Elem().FieldByName("BaseConfig").Set(reflect.ValueOf(*cfg))
|
||||
|
||||
if err := mapstructure.Decode(cfg.RawConfig, configValue); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode %s storage config: %w", cfg.Type, err)
|
||||
}
|
||||
|
||||
return configValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func LoadStorageConfigs(v *viper.Viper) ([]StorageConfig, error) {
|
||||
var baseConfigs []BaseConfig
|
||||
if err := v.UnmarshalKey("storages", &baseConfigs); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal storage configs: %w", err)
|
||||
}
|
||||
|
||||
var configs []StorageConfig
|
||||
for _, baseCfg := range baseConfigs {
|
||||
if !baseCfg.Enable {
|
||||
continue
|
||||
}
|
||||
|
||||
factory, ok := storageFactories[types.StorageType(baseCfg.Type)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported storage type: %s", baseCfg.Type)
|
||||
}
|
||||
|
||||
cfg, err := factory(&baseCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create storage config for %s: %w", baseCfg.Name, err)
|
||||
}
|
||||
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid storage config for %s: %w", baseCfg.Name, err)
|
||||
}
|
||||
|
||||
configs = append(configs, cfg)
|
||||
}
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
27
config/storage/local.go
Normal file
27
config/storage/local.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
type LocalStorageConfig struct {
|
||||
BaseConfig
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) Validate() error {
|
||||
if l.BasePath == "" {
|
||||
return fmt.Errorf("path is required for local storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeLocal
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) GetName() string {
|
||||
return l.Name
|
||||
}
|
||||
41
config/storage/minio.go
Normal file
41
config/storage/minio.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
type MinioStorageConfig struct {
|
||||
BaseConfig
|
||||
Endpoint string `toml:"endpoint" mapstructure:"endpoint" json:"endpoint"`
|
||||
AccessKeyID string `toml:"access_key_id" mapstructure:"access_key_id" json:"access_key_id"`
|
||||
SecretAccessKey string `toml:"secret_access_key" mapstructure:"secret_access_key" json:"secret_access_key"`
|
||||
BucketName string `toml:"bucket_name" mapstructure:"bucket_name" json:"bucket_name"`
|
||||
UseSSL bool `toml:"use_ssl" mapstructure:"use_ssl" json:"use_ssl"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) Validate() error {
|
||||
if m.Endpoint == "" {
|
||||
return fmt.Errorf("endpoint is required for minio storage")
|
||||
}
|
||||
if m.AccessKeyID == "" || m.SecretAccessKey == "" {
|
||||
return fmt.Errorf("access_key_id and secret_access_key are required for minio storage")
|
||||
}
|
||||
if m.BucketName == "" {
|
||||
return fmt.Errorf("bucket_name is required for minio storage")
|
||||
}
|
||||
if m.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for minio storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeMinio
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
16
config/storage/types.go
Normal file
16
config/storage/types.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package storage
|
||||
|
||||
import "github.com/krau/SaveAny-Bot/types"
|
||||
|
||||
type StorageConfig interface {
|
||||
Validate() error
|
||||
GetType() types.StorageType
|
||||
GetName() string
|
||||
}
|
||||
|
||||
type BaseConfig struct {
|
||||
Name string `toml:"name" mapstructure:"name" json:"name"`
|
||||
Type string `toml:"type" mapstructure:"type" json:"type"`
|
||||
Enable bool `toml:"enable" mapstructure:"enable" json:"enable"`
|
||||
RawConfig map[string]any `toml:"-" mapstructure:",remain"`
|
||||
}
|
||||
36
config/storage/webdav.go
Normal file
36
config/storage/webdav.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
type WebdavStorageConfig struct {
|
||||
BaseConfig
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) Validate() error {
|
||||
if w.URL == "" {
|
||||
return fmt.Errorf("url is required for webdav storage")
|
||||
}
|
||||
if w.Username == "" || w.Password == "" {
|
||||
return fmt.Errorf("username and password is required for webdav storage")
|
||||
}
|
||||
if w.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for webdav storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeWebdav
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) GetName() string {
|
||||
return w.Name
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type StorageConfig interface {
|
||||
Validate() error
|
||||
GetType() types.StorageType
|
||||
GetName() string
|
||||
}
|
||||
|
||||
// Base storage config
|
||||
type NewStorageConfig struct {
|
||||
Name string `toml:"name" mapstructure:"name" json:"name"`
|
||||
Type string `toml:"type" mapstructure:"type" json:"type"`
|
||||
Enable bool `toml:"enable" mapstructure:"enable" json:"enable"`
|
||||
RawConfig map[string]any `toml:"-" mapstructure:",remain"`
|
||||
}
|
||||
|
||||
var storageFactories = map[types.StorageType]func(cfg *NewStorageConfig) (StorageConfig, error){
|
||||
types.StorageTypeLocal: newLocalStorageConfig,
|
||||
types.StorageTypeAlist: newAlistStorageConfig,
|
||||
types.StorageTypeWebdav: newWebdavStorageConfig,
|
||||
types.StorageTypeMinio: newMinioStorageConfig,
|
||||
}
|
||||
|
||||
func LoadStorageConfigs(v *viper.Viper) ([]StorageConfig, error) {
|
||||
var baseConfigs []NewStorageConfig
|
||||
if err := v.UnmarshalKey("storages", &baseConfigs); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal storage configs: %w", err)
|
||||
}
|
||||
|
||||
var configs []StorageConfig
|
||||
for _, baseCfg := range baseConfigs {
|
||||
if !baseCfg.Enable {
|
||||
continue
|
||||
}
|
||||
|
||||
factory, ok := storageFactories[types.StorageType(baseCfg.Type)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported storage type: %s", baseCfg.Type)
|
||||
}
|
||||
|
||||
cfg, err := factory(&baseCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create storage config for %s: %w", baseCfg.Name, err)
|
||||
}
|
||||
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid storage config for %s: %w", baseCfg.Name, err)
|
||||
}
|
||||
|
||||
configs = append(configs, cfg)
|
||||
}
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func newLocalStorageConfig(cfg *NewStorageConfig) (StorageConfig, error) {
|
||||
var localCfg LocalStorageConfig
|
||||
localCfg.NewStorageConfig = *cfg
|
||||
|
||||
if err := mapstructure.Decode(cfg.RawConfig, &localCfg); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode local storage config: %w", err)
|
||||
}
|
||||
|
||||
return &localCfg, nil
|
||||
}
|
||||
|
||||
func newAlistStorageConfig(cfg *NewStorageConfig) (StorageConfig, error) {
|
||||
var alistCfg AlistStorageConfig
|
||||
alistCfg.NewStorageConfig = *cfg
|
||||
|
||||
if err := mapstructure.Decode(cfg.RawConfig, &alistCfg); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode alist storage config: %w", err)
|
||||
}
|
||||
|
||||
return &alistCfg, nil
|
||||
}
|
||||
|
||||
func newWebdavStorageConfig(cfg *NewStorageConfig) (StorageConfig, error) {
|
||||
var webdavCfg WebdavStorageConfig
|
||||
webdavCfg.NewStorageConfig = *cfg
|
||||
|
||||
if err := mapstructure.Decode(cfg.RawConfig, &webdavCfg); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode webdav storage config: %w", err)
|
||||
}
|
||||
|
||||
return &webdavCfg, nil
|
||||
}
|
||||
|
||||
func newMinioStorageConfig(cfg *NewStorageConfig) (StorageConfig, error) {
|
||||
var minioCfg MinioStorageConfig
|
||||
minioCfg.NewStorageConfig = *cfg
|
||||
if err := mapstructure.Decode(cfg.RawConfig, &minioCfg); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode minio storage config: %w", err)
|
||||
}
|
||||
return &minioCfg, nil
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
func (c *Config) GetStoragesByType(storageType types.StorageType) []StorageConfig {
|
||||
var storages []StorageConfig
|
||||
for _, storage := range c.Storages {
|
||||
if storage.GetType() == storageType {
|
||||
storages = append(storages, storage)
|
||||
}
|
||||
}
|
||||
return storages
|
||||
}
|
||||
|
||||
func (c *Config) GetStorageByName(name string) StorageConfig {
|
||||
for _, storage := range c.Storages {
|
||||
if storage.GetName() == name {
|
||||
return storage
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LocalStorageConfig struct {
|
||||
NewStorageConfig
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) Validate() error {
|
||||
if l.BasePath == "" {
|
||||
return fmt.Errorf("path is required for local storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeLocal
|
||||
}
|
||||
|
||||
func (l *LocalStorageConfig) GetName() string {
|
||||
return l.Name
|
||||
}
|
||||
|
||||
type AlistStorageConfig struct {
|
||||
NewStorageConfig
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
Token string `toml:"token" mapstructure:"token" json:"token"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
TokenExp int64 `toml:"token_exp" mapstructure:"token_exp" json:"token_exp"`
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) Validate() error {
|
||||
if a.URL == "" {
|
||||
return fmt.Errorf("url is required for alist storage")
|
||||
}
|
||||
if a.Token == "" && (a.Username == "" || a.Password == "") {
|
||||
return fmt.Errorf("username and password or token is required for alist storage")
|
||||
}
|
||||
if a.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for alist storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeAlist
|
||||
}
|
||||
|
||||
func (a *AlistStorageConfig) GetName() string {
|
||||
return a.Name
|
||||
}
|
||||
|
||||
type WebdavStorageConfig struct {
|
||||
NewStorageConfig
|
||||
URL string `toml:"url" mapstructure:"url" json:"url"`
|
||||
Username string `toml:"username" mapstructure:"username" json:"username"`
|
||||
Password string `toml:"password" mapstructure:"password" json:"password"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) Validate() error {
|
||||
if w.URL == "" {
|
||||
return fmt.Errorf("url is required for webdav storage")
|
||||
}
|
||||
if w.Username == "" || w.Password == "" {
|
||||
return fmt.Errorf("username and password is required for webdav storage")
|
||||
}
|
||||
if w.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for webdav storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeWebdav
|
||||
}
|
||||
|
||||
func (w *WebdavStorageConfig) GetName() string {
|
||||
return w.Name
|
||||
}
|
||||
|
||||
type MinioStorageConfig struct {
|
||||
NewStorageConfig
|
||||
Endpoint string `toml:"endpoint" mapstructure:"endpoint" json:"endpoint"`
|
||||
AccessKeyID string `toml:"access_key_id" mapstructure:"access_key_id" json:"access_key_id"`
|
||||
SecretAccessKey string `toml:"secret_access_key" mapstructure:"secret_access_key" json:"secret_access_key"`
|
||||
BucketName string `toml:"bucket_name" mapstructure:"bucket_name" json:"bucket_name"`
|
||||
UseSSL bool `toml:"use_ssl" mapstructure:"use_ssl" json:"use_ssl"`
|
||||
BasePath string `toml:"base_path" mapstructure:"base_path" json:"base_path"`
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) Validate() error {
|
||||
if m.Endpoint == "" {
|
||||
return fmt.Errorf("endpoint is required for minio storage")
|
||||
}
|
||||
if m.AccessKeyID == "" || m.SecretAccessKey == "" {
|
||||
return fmt.Errorf("access_key_id and secret_access_key are required for minio storage")
|
||||
}
|
||||
if m.BucketName == "" {
|
||||
return fmt.Errorf("bucket_name is required for minio storage")
|
||||
}
|
||||
if m.BasePath == "" {
|
||||
return fmt.Errorf("base_path is required for minio storage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) GetType() types.StorageType {
|
||||
return types.StorageTypeMinio
|
||||
}
|
||||
|
||||
func (m *MinioStorageConfig) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@@ -17,13 +18,11 @@ type Config struct {
|
||||
|
||||
Users []userConfig `toml:"users" mapstructure:"users" json:"users"`
|
||||
|
||||
Temp tempConfig `toml:"temp" mapstructure:"temp"`
|
||||
Log logConfig `toml:"log" mapstructure:"log"`
|
||||
DB dbConfig `toml:"db" mapstructure:"db"`
|
||||
Telegram telegramConfig `toml:"telegram" mapstructure:"telegram"`
|
||||
Storages []StorageConfig `toml:"-" mapstructure:"-" json:"storages"`
|
||||
// Deprecated
|
||||
DeprecatedStorage deprecatedStorageConfig `toml:"storage" mapstructure:"storage"`
|
||||
Temp tempConfig `toml:"temp" mapstructure:"temp"`
|
||||
Log logConfig `toml:"log" mapstructure:"log"`
|
||||
DB dbConfig `toml:"db" mapstructure:"db"`
|
||||
Telegram telegramConfig `toml:"telegram" mapstructure:"telegram"`
|
||||
Storages []storage.StorageConfig `toml:"-" mapstructure:"-" json:"storages"`
|
||||
}
|
||||
|
||||
type tempConfig struct {
|
||||
@@ -58,6 +57,15 @@ type proxyConfig struct {
|
||||
|
||||
var Cfg *Config
|
||||
|
||||
func (c Config) GetStorageByName(name string) storage.StorageConfig {
|
||||
for _, storage := range c.Storages {
|
||||
if storage.GetName() == name {
|
||||
return storage
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Init() error {
|
||||
viper.SetConfigName("config")
|
||||
viper.AddConfigPath(".")
|
||||
@@ -102,38 +110,12 @@ func Init() error {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if Cfg.Telegram.Admins != nil {
|
||||
fmt.Println("警告: 你正在使用旧版 Telegram 管理员配置, 该配置下的用户将可用所有存储.\ntelegram.admins 未来版本将会被废弃, 请参考新的配置文件模板, 使用 users 配置替代.")
|
||||
for _, admin := range Cfg.Telegram.Admins {
|
||||
found := false
|
||||
for _, user := range Cfg.Users {
|
||||
if user.ID == admin {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
Cfg.Users = append(Cfg.Users, userConfig{
|
||||
ID: admin,
|
||||
Storages: []string{},
|
||||
Blacklist: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
storagesConfig, err := LoadStorageConfigs(viper.GetViper())
|
||||
storagesConfig, err := storage.LoadStorageConfigs(viper.GetViper())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading storage configs: %w", err)
|
||||
}
|
||||
Cfg.Storages = storagesConfig
|
||||
|
||||
if Cfg.DeprecatedStorage != (deprecatedStorageConfig{}) {
|
||||
fmt.Println("\n警告: 你正在使用旧版存储配置, 未来版本将会被废弃.\n请参考新的配置文件模板.")
|
||||
transformDeprecatedStorageConfig()
|
||||
}
|
||||
|
||||
storageNames := make(map[string]struct{})
|
||||
for _, storage := range Cfg.Storages {
|
||||
if _, ok := storageNames[storage.GetName()]; ok {
|
||||
|
||||
4
go.mod
4
go.mod
@@ -18,7 +18,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/AnimeKaizoku/cacher v1.0.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
@@ -33,7 +32,6 @@ require (
|
||||
github.com/go-faster/xor v1.0.0 // indirect
|
||||
github.com/go-faster/yaml v0.4.6 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/google/go-github/v30 v30.1.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
@@ -67,7 +65,6 @@ require (
|
||||
golang.org/x/oauth2 v0.26.0 // indirect
|
||||
golang.org/x/tools v0.30.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gorm.io/driver/mysql v1.5.6 // indirect
|
||||
modernc.org/libc v1.61.13 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.8.2 // indirect
|
||||
@@ -105,6 +102,5 @@ require (
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/datatypes v1.2.5
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
32
go.sum
32
go.sum
@@ -1,5 +1,3 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/AnimeKaizoku/cacher v1.0.2 h1:7Bf5qRylWb7q2Evib0OXlhG37/t7BP2HK/7IyPvSmGQ=
|
||||
github.com/AnimeKaizoku/cacher v1.0.2/go.mod h1:jw0de/b0K6W7Y3T9rHCMGVKUf6oG7hENNcssxYcZTCc=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
@@ -55,15 +53,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -101,14 +92,6 @@ github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7V
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
@@ -131,10 +114,6 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.81 h1:SzhMN0TQ6T/xSBu6Nvw3M5M8voM+Ht8RH3hE8S7zxaA=
|
||||
@@ -269,17 +248,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
|
||||
gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
|
||||
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
|
||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
||||
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
||||
gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
|
||||
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
config "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
config "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
config "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
config "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
"github.com/minio/minio-go/v7"
|
||||
|
||||
@@ -6,16 +6,17 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
sc "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
"github.com/krau/SaveAny-Bot/storage/alist"
|
||||
"github.com/krau/SaveAny-Bot/storage/local"
|
||||
"github.com/krau/SaveAny-Bot/storage/webdav"
|
||||
"github.com/krau/SaveAny-Bot/storage/minio"
|
||||
"github.com/krau/SaveAny-Bot/storage/webdav"
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
Init(cfg config.StorageConfig) error
|
||||
Init(cfg sc.StorageConfig) error
|
||||
Type() types.StorageType
|
||||
Name() string
|
||||
JoinStoragePath(task types.Task) string
|
||||
@@ -94,7 +95,7 @@ var storageConstructors = map[string]StorageConstructor{
|
||||
string(types.StorageTypeMinio): func() Storage { return new(minio.Minio) },
|
||||
}
|
||||
|
||||
func NewStorage(cfg config.StorageConfig) (Storage, error) {
|
||||
func NewStorage(cfg sc.StorageConfig) (Storage, error) {
|
||||
constructor, ok := storageConstructors[string(cfg.GetType())]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("不支持的存储类型: %s", cfg.GetType())
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/krau/SaveAny-Bot/config"
|
||||
config "github.com/krau/SaveAny-Bot/config/storage"
|
||||
"github.com/krau/SaveAny-Bot/logger"
|
||||
"github.com/krau/SaveAny-Bot/types"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user