mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-11-25 03:15:19 +08:00
* feat(cache): improve cache management * feat(disk-usage): add cache * feat(disk-usage): add refresh * fix(disk-usage): cache with ttl * feat(cache): implement KeyedCache and TypedCache for improved caching mechanism * fix(copy): update object retrieval to use Get instead of GetUnwrap * refactor(cache): simplify DirectoryCache structure and improve object management * fix(cache): correct cache entry initialization and key deletion logic in TypedCache * refactor(driver): remove GetObjInfo interface and simplify Link function logic https://github.com/OpenListTeam/OpenList/pull/888/files#r2430925783 * fix(link): optimize link retrieval and caching logic * refactor(cache): consolidate cache management and improve directory cache handling * fix(cache): add cache control based on storage configuration in List function * . * refactor: replace fmt.Sprintf with strconv for integer conversions * refactor(cache): enhance cache entry management with Expirable interface * fix(cache): improve link reference acquisition logic to handle expiration * refactor: replace OnlyLinkMFile with NoLinkSF in driver configurations and logic * refactor(link): enhance link caching logic with dynamic type keys based on IP and User-Agent * feat(drivers): add LinkCacheType to driver configurations for enhanced caching * refactor(cache): streamline directory object management in cache operations * refactor(cache): remove unnecessary 'dirty' field from CacheEntry structure * refactor(cache): replace 'dirty' field with bitwise flags * refactor(io): 调高SyncClosers.AcquireReference的优先级 * refactor(link): 优化链接获取逻辑,增加重 * refactor(link): 添加RequireReference字段以增强链接管理 * refactor(link): 移除MFile字段,改用RangeReader * refactor: 移除不必要的NoLinkSF字段 * refactor(cache): 修改目录缓存的脏标志定义和更新逻辑 * feat(cache): add expiration gc --------- Co-authored-by: KirCute <951206789@qq.com> Co-authored-by: KirCute <kircute@foxmail.com> Co-authored-by: j2rong4cn <j2rong@qq.com>
185 lines
4.4 KiB
Go
185 lines
4.4 KiB
Go
package chaoxing
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto/aes"
|
||
"crypto/cipher"
|
||
"encoding/base64"
|
||
"errors"
|
||
"fmt"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||
"github.com/go-resty/resty/v2"
|
||
)
|
||
|
||
func (d *ChaoXing) requestDownload(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||
u := d.conf.DowloadApi + pathname
|
||
req := base.RestyClient.R()
|
||
req.SetHeaders(map[string]string{
|
||
"Cookie": d.Cookie,
|
||
"Accept": "application/json, text/plain, */*",
|
||
"Referer": d.conf.referer,
|
||
})
|
||
if callback != nil {
|
||
callback(req)
|
||
}
|
||
if resp != nil {
|
||
req.SetResult(resp)
|
||
}
|
||
var e Resp
|
||
req.SetError(&e)
|
||
res, err := req.Execute(method, u)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return res.Body(), nil
|
||
}
|
||
|
||
func (d *ChaoXing) request(pathname string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||
u := d.conf.api + pathname
|
||
if strings.Contains(pathname, "getUploadConfig") {
|
||
u = pathname
|
||
}
|
||
req := base.RestyClient.R()
|
||
req.SetHeaders(map[string]string{
|
||
"Cookie": d.Cookie,
|
||
"Accept": "application/json, text/plain, */*",
|
||
"Referer": d.conf.referer,
|
||
})
|
||
if callback != nil {
|
||
callback(req)
|
||
}
|
||
if resp != nil {
|
||
req.SetResult(resp)
|
||
}
|
||
var e Resp
|
||
req.SetError(&e)
|
||
res, err := req.Execute(method, u)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return res.Body(), nil
|
||
}
|
||
|
||
func (d *ChaoXing) GetFiles(parent string) ([]File, error) {
|
||
files := make([]File, 0)
|
||
query := map[string]string{
|
||
"bbsid": d.Addition.Bbsid,
|
||
"folderId": parent,
|
||
"recType": "1",
|
||
}
|
||
var resp ListFileResp
|
||
_, err := d.request("/pc/resource/getResourceList", http.MethodGet, func(req *resty.Request) {
|
||
req.SetQueryParams(query)
|
||
}, &resp)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if resp.Result != 1 {
|
||
msg := fmt.Sprintf("error code is:%d", resp.Result)
|
||
return nil, errors.New(msg)
|
||
}
|
||
if len(resp.List) > 0 {
|
||
files = append(files, resp.List...)
|
||
}
|
||
querys := map[string]string{
|
||
"bbsid": d.Addition.Bbsid,
|
||
"folderId": parent,
|
||
"recType": "2",
|
||
}
|
||
var resps ListFileResp
|
||
_, err = d.request("/pc/resource/getResourceList", http.MethodGet, func(req *resty.Request) {
|
||
req.SetQueryParams(querys)
|
||
}, &resps)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for _, file := range resps.List {
|
||
// 手机端超星上传的文件没有fileID字段,但ObjectID与fileID相同,可代替
|
||
if file.Content.FileID == "" {
|
||
file.Content.FileID = file.Content.ObjectID
|
||
}
|
||
files = append(files, file)
|
||
}
|
||
return files, nil
|
||
}
|
||
|
||
func EncryptByAES(message, key string) (string, error) {
|
||
aesKey := []byte(key)
|
||
plainText := []byte(message)
|
||
block, err := aes.NewCipher(aesKey)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
iv := aesKey[:aes.BlockSize]
|
||
mode := cipher.NewCBCEncrypter(block, iv)
|
||
padding := aes.BlockSize - len(plainText)%aes.BlockSize
|
||
paddedText := append(plainText, byte(padding))
|
||
for i := 0; i < padding-1; i++ {
|
||
paddedText = append(paddedText, byte(padding))
|
||
}
|
||
ciphertext := make([]byte, len(paddedText))
|
||
mode.CryptBlocks(ciphertext, paddedText)
|
||
encrypted := base64.StdEncoding.EncodeToString(ciphertext)
|
||
return encrypted, nil
|
||
}
|
||
|
||
func CookiesToString(cookies []*http.Cookie) string {
|
||
var cookieStr string
|
||
for _, cookie := range cookies {
|
||
cookieStr += cookie.Name + "=" + cookie.Value + "; "
|
||
}
|
||
if len(cookieStr) > 2 {
|
||
cookieStr = cookieStr[:len(cookieStr)-2]
|
||
}
|
||
return cookieStr
|
||
}
|
||
|
||
func (d *ChaoXing) Login() (string, error) {
|
||
transferKey := "u2oh6Vu^HWe4_AES"
|
||
body := &bytes.Buffer{}
|
||
writer := multipart.NewWriter(body)
|
||
uname, err := EncryptByAES(d.Addition.UserName, transferKey)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
password, err := EncryptByAES(d.Addition.Password, transferKey)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
err = writer.WriteField("uname", uname)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
err = writer.WriteField("password", password)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
err = writer.WriteField("t", "true")
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
err = writer.Close()
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
// Create the request
|
||
req, err := http.NewRequest(http.MethodPost, "https://passport2.chaoxing.com/fanyalogin", body)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||
req.Header.Set("Content-Length", strconv.Itoa(body.Len()))
|
||
resp, err := http.DefaultClient.Do(req)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
defer resp.Body.Close()
|
||
return CookiesToString(resp.Cookies()), nil
|
||
|
||
}
|