feat: init commit

This commit is contained in:
krau
2024-10-10 23:31:01 +08:00
commit 1cbcebc148
31 changed files with 1673 additions and 0 deletions

109
storage/alist/alist.go Normal file
View File

@@ -0,0 +1,109 @@
package alist
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"path"
"time"
"github.com/imroc/req/v3"
"github.com/krau/SaveAny-Bot/config"
"github.com/krau/SaveAny-Bot/logger"
)
type Alist struct{}
var (
basePath string
baseUrl string
reqClient *req.Client
loginReq *loginRequset
ErrAlistLoginFailed = errors.New("failed to login to Alist")
)
type loginRequset struct {
Username string `json:"username"`
Password string `json:"password"`
}
type loginResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
Token string `json:"token"`
} `json:"data"`
}
func getToken() (string, error) {
resp, err := reqClient.R().SetBodyJsonMarshal(loginReq).Post("/api/auth/login")
if err != nil {
return "", err
}
var loginResp loginResponse
if err := json.Unmarshal(resp.Bytes(), &loginResp); err != nil {
return "", err
}
if loginResp.Code != http.StatusOK {
return "", fmt.Errorf("%w: %s", ErrAlistLoginFailed, loginResp.Message)
}
return loginResp.Data.Token, nil
}
func refreshToken(client *req.Client) {
for {
time.Sleep(time.Duration(config.Cfg.Storage.Alist.TokenExp) * time.Second)
token, err := getToken()
if err != nil {
logger.L.Errorf("Failed to refresh jwt token: %v", err)
continue
}
client.SetCommonHeader("Authorization", token)
logger.L.Info("Refreshed Alist jwt token")
}
}
func (a *Alist) Init() {
basePath = config.Cfg.Storage.Alist.BasePath
baseUrl = config.Cfg.Storage.Alist.URL
reqClient = req.C().SetTLSHandshakeTimeout(time.Second * 10).SetBaseURL(baseUrl)
loginReq = &loginRequset{
Username: config.Cfg.Storage.Alist.Username,
Password: config.Cfg.Storage.Alist.Password,
}
token, err := getToken()
if err != nil {
logger.L.Fatalf("Failed to login to Alist: %v", err)
os.Exit(1)
}
logger.L.Debug("Logged in to Alist")
reqClient.SetCommonHeader("Authorization", token)
go refreshToken(reqClient)
}
func (a *Alist) Save(ctx context.Context, filePath, storagePath string) error {
storagePath = path.Join(basePath, storagePath)
file, err := os.Open(filePath)
if err != nil {
return err
}
resp, err := reqClient.R().
SetContext(ctx).
SetBody(file).
SetHeaders(map[string]string{
"File-Path": url.PathEscape(storagePath),
"As-Task": "true",
}).Put("/api/fs/put")
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to save file to Alist: %s", resp.Status)
}
return nil
}

25
storage/local/local.go Normal file
View File

@@ -0,0 +1,25 @@
package local
import (
"context"
"os"
"path/filepath"
"github.com/duke-git/lancet/v2/fileutil"
"github.com/krau/SaveAny-Bot/config"
"github.com/krau/SaveAny-Bot/logger"
)
type Local struct{}
func (l *Local) Init() {
err := os.MkdirAll(config.Cfg.Storage.Local.BasePath, os.ModePerm)
if err != nil {
logger.L.Fatalf("Failed to create local storage directory: %s", err)
os.Exit(1)
}
}
func (l *Local) Save(ctx context.Context, filePath, storagePath string) error {
return fileutil.CopyFile(filePath, filepath.Join(config.Cfg.Storage.Local.BasePath, storagePath))
}

59
storage/storage.go Normal file
View File

@@ -0,0 +1,59 @@
package storage
import (
"context"
"errors"
"sync"
"github.com/krau/SaveAny-Bot/config"
"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/types"
)
type Storage interface {
Init()
Save(cttx context.Context, filePath, storagePath string) error
}
var Storages = make(map[types.StorageType]Storage)
func Init() {
logger.L.Debug("Initializing storage...")
if config.Cfg.Storage.Alist.Enable {
Storages[types.Alist] = new(alist.Alist)
Storages[types.Alist].Init()
}
if config.Cfg.Storage.Local.Enable {
Storages[types.Local] = new(local.Local)
Storages[types.Local].Init()
}
logger.L.Debug("Storage initialized")
}
func Save(storageType types.StorageType, ctx context.Context, filePath, storagePath string) error {
if ctx == nil {
ctx = context.Background()
}
if storageType != types.StorageAll {
return Storages[storageType].Save(ctx, filePath, storagePath)
}
errs := make([]error, 0)
var wg sync.WaitGroup
for _, storage := range Storages {
wg.Add(1)
go func(storage Storage) {
defer wg.Done()
if err := storage.Save(ctx, filePath, storagePath); err != nil {
errs = append(errs, err)
}
}(storage)
}
wg.Wait()
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}