mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-07 10:37:39 +08:00
feat: support alist as a storage
This commit is contained in:
194
pkg/alist/alist.go
Normal file
194
pkg/alist/alist.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package alist
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Resposne[T any] struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Username string
|
||||
Password string
|
||||
URL string
|
||||
}
|
||||
|
||||
func New(cfg *Config) *Client {
|
||||
cfg.URL = strings.Trim(cfg.URL, "/")
|
||||
return &Client{
|
||||
cfg: cfg,
|
||||
http: http.DefaultClient,
|
||||
}
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
cfg *Config
|
||||
http *http.Client
|
||||
token string
|
||||
}
|
||||
|
||||
func (c *Client) Login() (string, error) {
|
||||
p := map[string]string{
|
||||
"username": c.cfg.Username,
|
||||
"password": c.cfg.Password,
|
||||
}
|
||||
data, _ := json.Marshal(p)
|
||||
resp, err := c.http.Post(c.cfg.URL+loginUrl, "application/json", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "login")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
d1, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "read body")
|
||||
}
|
||||
var rp Resposne[map[string]string]
|
||||
|
||||
err = json.Unmarshal(d1, &rp)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "json")
|
||||
}
|
||||
if rp.Code != 200 {
|
||||
return "", errors.Errorf("alist error: code %d, %s", rp.Code, rp.Message)
|
||||
}
|
||||
c.token = rp.Data["token"]
|
||||
return c.token, nil
|
||||
}
|
||||
|
||||
type LsInfo struct {
|
||||
Content []struct {
|
||||
Name string `json:"name"`
|
||||
Size int `json:"size"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Modified time.Time `json:"modified"`
|
||||
Created time.Time `json:"created"`
|
||||
Sign string `json:"sign"`
|
||||
Thumb string `json:"thumb"`
|
||||
Type int `json:"type"`
|
||||
Hashinfo string `json:"hashinfo"`
|
||||
HashInfo any `json:"hash_info"`
|
||||
} `json:"content"`
|
||||
Total int `json:"total"`
|
||||
Readme string `json:"readme"`
|
||||
Header string `json:"header"`
|
||||
Write bool `json:"write"`
|
||||
Provider string `json:"provider"`
|
||||
}
|
||||
|
||||
func (c *Client) Ls(dir string) (*LsInfo, error) {
|
||||
in := map[string]string{
|
||||
"path": dir,
|
||||
}
|
||||
|
||||
resp, err := c.post(c.cfg.URL+lsUrl, in)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "http")
|
||||
}
|
||||
|
||||
var out Resposne[LsInfo]
|
||||
err = json.Unmarshal(resp, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if out.Code != 200 {
|
||||
return nil, errors.Errorf("alist error: code %d, %s", out.Code, out.Message)
|
||||
}
|
||||
return &out.Data, nil
|
||||
}
|
||||
|
||||
func (c *Client) Mkdir(dir string) error {
|
||||
in := map[string]string{
|
||||
"path": dir,
|
||||
}
|
||||
resp, err := c.post(c.cfg.URL+mkdirUrl, in)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "http")
|
||||
}
|
||||
var out Resposne[any]
|
||||
err = json.Unmarshal(resp, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if out.Code != 200 {
|
||||
return errors.Errorf("alist error: code %d, %s", out.Code, out.Message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) post(url string, body interface{}) ([]byte, error) {
|
||||
data, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new request")
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", c.token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "http")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
d1, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "read body")
|
||||
}
|
||||
return d1, nil
|
||||
}
|
||||
|
||||
type UploadStreamResponse struct {
|
||||
Task struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
State int `json:"state"`
|
||||
Status string `json:"status"`
|
||||
Progress int `json:"progress"`
|
||||
Error string `json:"error"`
|
||||
} `json:"task"`
|
||||
}
|
||||
|
||||
func (c *Client) UploadStream(reader io.Reader, toDir string) (*UploadStreamResponse, error) {
|
||||
req, err := http.NewRequest(http.MethodPost, c.cfg.URL+streamUploadUrl, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Authorization", "{{alist_token}}")
|
||||
req.Header.Add("File-Path", toDir)
|
||||
req.Header.Add("As-Task", "true")
|
||||
req.Header.Add("Content-Length", "")
|
||||
req.Header.Add("Content-Type", "application/octet-stream")
|
||||
res, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
d1, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out Resposne[UploadStreamResponse]
|
||||
err = json.Unmarshal(d1, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if out.Code != 200 {
|
||||
return nil, errors.Errorf("alist error: code %d, %s", out.Code, out.Message)
|
||||
}
|
||||
|
||||
return &out.Data, nil
|
||||
}
|
||||
Reference in New Issue
Block a user