mirror of https://github.com/Xhofe/alist
300 lines
7.1 KiB
Go
300 lines
7.1 KiB
Go
package chaoxing
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/alist-org/alist/v3/internal/driver"
|
|
"github.com/alist-org/alist/v3/internal/errs"
|
|
"github.com/alist-org/alist/v3/internal/model"
|
|
"github.com/alist-org/alist/v3/internal/op"
|
|
"github.com/alist-org/alist/v3/pkg/cron"
|
|
"github.com/alist-org/alist/v3/pkg/utils"
|
|
"github.com/go-resty/resty/v2"
|
|
"google.golang.org/appengine/log"
|
|
)
|
|
|
|
type ChaoXing struct {
|
|
model.Storage
|
|
Addition
|
|
cron *cron.Cron
|
|
config driver.Config
|
|
conf Conf
|
|
}
|
|
|
|
func (d *ChaoXing) Config() driver.Config {
|
|
return d.config
|
|
}
|
|
|
|
func (d *ChaoXing) GetAddition() driver.Additional {
|
|
return &d.Addition
|
|
}
|
|
|
|
func (d *ChaoXing) refreshCookie() error {
|
|
cookie, err := d.Login()
|
|
if err != nil {
|
|
d.Status = err.Error()
|
|
op.MustSaveDriverStorage(d)
|
|
return nil
|
|
}
|
|
d.Addition.Cookie = cookie
|
|
op.MustSaveDriverStorage(d)
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Init(ctx context.Context) error {
|
|
err := d.refreshCookie()
|
|
if err != nil {
|
|
log.Errorf(ctx, err.Error())
|
|
}
|
|
d.cron = cron.NewCron(time.Hour * 12)
|
|
d.cron.Do(func() {
|
|
err = d.refreshCookie()
|
|
if err != nil {
|
|
log.Errorf(ctx, err.Error())
|
|
}
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Drop(ctx context.Context) error {
|
|
if d.cron != nil {
|
|
d.cron.Stop()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
|
files, err := d.GetFiles(dir.GetID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
|
return fileToObj(src), nil
|
|
})
|
|
}
|
|
|
|
func (d *ChaoXing) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
|
var resp DownResp
|
|
ua := d.conf.ua
|
|
fileId := strings.Split(file.GetID(), "$")[1]
|
|
_, err := d.requestDownload("/screen/note_note/files/status/"+fileId, http.MethodPost, func(req *resty.Request) {
|
|
req.SetHeader("User-Agent", ua)
|
|
}, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
u := resp.Download
|
|
return &model.Link{
|
|
URL: u,
|
|
Header: http.Header{
|
|
"Cookie": []string{d.Cookie},
|
|
"Referer": []string{d.conf.referer},
|
|
"User-Agent": []string{ua},
|
|
},
|
|
Concurrency: 2,
|
|
PartSize: 10 * utils.MB,
|
|
}, nil
|
|
}
|
|
|
|
func (d *ChaoXing) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
|
query := map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"name": dirName,
|
|
"pid": parentDir.GetID(),
|
|
}
|
|
var resp ListFileResp
|
|
_, err := d.request("/pc/resource/addResourceFolder", http.MethodGet, func(req *resty.Request) {
|
|
req.SetQueryParams(query)
|
|
}, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Result != 1 {
|
|
msg := fmt.Sprintf("error:%s", resp.Msg)
|
|
return errors.New(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|
query := map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"folderIds": srcObj.GetID(),
|
|
"targetId": dstDir.GetID(),
|
|
}
|
|
if !srcObj.IsDir() {
|
|
query = map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"recIds": strings.Split(srcObj.GetID(), "$")[0],
|
|
"targetId": dstDir.GetID(),
|
|
}
|
|
}
|
|
var resp ListFileResp
|
|
_, err := d.request("/pc/resource/moveResource", http.MethodGet, func(req *resty.Request) {
|
|
req.SetQueryParams(query)
|
|
}, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !resp.Status {
|
|
msg := fmt.Sprintf("error:%s", resp.Msg)
|
|
return errors.New(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
|
query := map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"folderId": srcObj.GetID(),
|
|
"name": newName,
|
|
}
|
|
path := "/pc/resource/updateResourceFolderName"
|
|
if !srcObj.IsDir() {
|
|
// path = "/pc/resource/updateResourceFileName"
|
|
// query = map[string]string{
|
|
// "bbsid": d.Addition.Bbsid,
|
|
// "recIds": strings.Split(srcObj.GetID(), "$")[0],
|
|
// "name": newName,
|
|
// }
|
|
return errors.New("此网盘不支持修改文件名")
|
|
}
|
|
var resp ListFileResp
|
|
_, err := d.request(path, http.MethodGet, func(req *resty.Request) {
|
|
req.SetQueryParams(query)
|
|
}, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Result != 1 {
|
|
msg := fmt.Sprintf("error:%s", resp.Msg)
|
|
return errors.New(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|
// TODO copy obj, optional
|
|
return errs.NotImplement
|
|
}
|
|
|
|
func (d *ChaoXing) Remove(ctx context.Context, obj model.Obj) error {
|
|
query := map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"folderIds": obj.GetID(),
|
|
}
|
|
path := "/pc/resource/deleteResourceFolder"
|
|
var resp ListFileResp
|
|
if !obj.IsDir() {
|
|
path = "/pc/resource/deleteResourceFile"
|
|
query = map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"recIds": strings.Split(obj.GetID(), "$")[0],
|
|
}
|
|
}
|
|
_, err := d.request(path, http.MethodGet, func(req *resty.Request) {
|
|
req.SetQueryParams(query)
|
|
}, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Result != 1 {
|
|
msg := fmt.Sprintf("error:%s", resp.Msg)
|
|
return errors.New(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *ChaoXing) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
|
var resp UploadDataRsp
|
|
_, err := d.request("https://noteyd.chaoxing.com/pc/files/getUploadConfig", http.MethodGet, func(req *resty.Request) {
|
|
}, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Result != 1 {
|
|
return errors.New("get upload data error")
|
|
}
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
filePart, err := writer.CreateFormFile("file", stream.GetName())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = utils.CopyWithBuffer(filePart, stream)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = writer.WriteField("_token", resp.Msg.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = writer.WriteField("puid", fmt.Sprintf("%d", resp.Msg.Puid))
|
|
if err != nil {
|
|
fmt.Println("Error writing param2 to request body:", err)
|
|
return err
|
|
}
|
|
err = writer.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req, err := http.NewRequest("POST", "https://pan-yz.chaoxing.com/upload", body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
req.Header.Set("Content-Length", fmt.Sprintf("%d", body.Len()))
|
|
resps, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resps.Body.Close()
|
|
bodys, err := io.ReadAll(resps.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var fileRsp UploadFileDataRsp
|
|
err = json.Unmarshal(bodys, &fileRsp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if fileRsp.Msg != "success" {
|
|
return errors.New(fileRsp.Msg)
|
|
}
|
|
uploadDoneParam := UploadDoneParam{Key: fileRsp.ObjectID, Cataid: "100000019", Param: fileRsp.Data}
|
|
params, err := json.Marshal(uploadDoneParam)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
query := map[string]string{
|
|
"bbsid": d.Addition.Bbsid,
|
|
"pid": dstDir.GetID(),
|
|
"type": "yunpan",
|
|
"params": url.QueryEscape("[" + string(params) + "]"),
|
|
}
|
|
var respd ListFileResp
|
|
_, err = d.request("/pc/resource/addResource", http.MethodGet, func(req *resty.Request) {
|
|
req.SetQueryParams(query)
|
|
}, &respd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if respd.Result != 1 {
|
|
msg := fmt.Sprintf("error:%v", resp.Msg)
|
|
return errors.New(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var _ driver.Driver = (*ChaoXing)(nil)
|