mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-07-20 12:11:29 +08:00
feat: init commit
This commit is contained in:
109
storage/alist/alist.go
Normal file
109
storage/alist/alist.go
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user