mirror of https://github.com/Xhofe/alist
parent
9f08353d31
commit
c9ea9bce81
|
@ -2,9 +2,7 @@ package lanzou
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
|
@ -19,6 +17,8 @@ type LanZou struct {
|
|||
model.Storage
|
||||
uid string
|
||||
vei string
|
||||
|
||||
flag int32
|
||||
}
|
||||
|
||||
func (d *LanZou) Config() driver.Config {
|
||||
|
@ -30,16 +30,18 @@ func (d *LanZou) GetAddition() driver.Additional {
|
|||
}
|
||||
|
||||
func (d *LanZou) Init(ctx context.Context) (err error) {
|
||||
if d.IsCookie() {
|
||||
switch d.Type {
|
||||
case "account":
|
||||
_, err := d.Login()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fallthrough
|
||||
case "cookie":
|
||||
if d.RootFolderID == "" {
|
||||
d.RootFolderID = "-1"
|
||||
}
|
||||
ylogin := regexp.MustCompile("ylogin=(.*?);").FindStringSubmatch(d.Cookie)
|
||||
if len(ylogin) < 2 {
|
||||
return fmt.Errorf("cookie does not contain ylogin")
|
||||
}
|
||||
d.uid = ylogin[1]
|
||||
d.vei, err = d.getVei()
|
||||
d.vei, d.uid, err = d.getVeiAndUid()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -51,7 +53,7 @@ func (d *LanZou) Drop(ctx context.Context) error {
|
|||
|
||||
// 获取的大小和时间不准确
|
||||
func (d *LanZou) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
return d.GetAllFiles(dir.GetID())
|
||||
} else {
|
||||
return d.GetFileOrFolderByShareUrl(dir.GetID(), d.SharePassword)
|
||||
|
@ -119,7 +121,7 @@ func (d *LanZou) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
|||
}
|
||||
|
||||
func (d *LanZou) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
data, err := d.doupload(func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
req.SetFormData(map[string]string{
|
||||
|
@ -137,11 +139,11 @@ func (d *LanZou) MakeDir(ctx context.Context, parentDir model.Obj, dirName strin
|
|||
FolID: utils.Json.Get(data, "text").ToString(),
|
||||
}, nil
|
||||
}
|
||||
return nil, errs.NotImplement
|
||||
return nil, errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *LanZou) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
if !srcObj.IsDir() {
|
||||
_, err := d.doupload(func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
|
@ -157,11 +159,11 @@ func (d *LanZou) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj,
|
|||
return srcObj, nil
|
||||
}
|
||||
}
|
||||
return nil, errs.NotImplement
|
||||
return nil, errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *LanZou) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
if !srcObj.IsDir() {
|
||||
_, err := d.doupload(func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
|
@ -179,11 +181,11 @@ func (d *LanZou) Rename(ctx context.Context, srcObj model.Obj, newName string) (
|
|||
return srcObj, nil
|
||||
}
|
||||
}
|
||||
return nil, errs.NotImplement
|
||||
return nil, errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *LanZou) Remove(ctx context.Context, obj model.Obj) error {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
_, err := d.doupload(func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
if obj.IsDir() {
|
||||
|
@ -200,13 +202,13 @@ func (d *LanZou) Remove(ctx context.Context, obj model.Obj) error {
|
|||
}, nil)
|
||||
return err
|
||||
}
|
||||
return errs.NotImplement
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *LanZou) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
|
||||
if d.IsCookie() {
|
||||
if d.IsCookie() || d.IsAccount() {
|
||||
var resp RespText[[]FileOrFolder]
|
||||
_, err := d._post(d.BaseUrl+"/fileup.php", func(req *resty.Request) {
|
||||
_, err := d._post(d.BaseUrl+"/html5up.php", func(req *resty.Request) {
|
||||
req.SetFormData(map[string]string{
|
||||
"task": "1",
|
||||
"vie": "2",
|
||||
|
@ -221,5 +223,5 @@ func (d *LanZou) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||
}
|
||||
return &resp.Text[0], nil
|
||||
}
|
||||
return nil, errs.NotImplement
|
||||
return nil, errs.NotSupport
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package lanzou
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -190,3 +191,14 @@ func GetExpirationTime(url string) (etime time.Duration) {
|
|||
etime = time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||
return
|
||||
}
|
||||
|
||||
func CookieToString(cookies []*http.Cookie) string {
|
||||
if cookies == nil {
|
||||
return ""
|
||||
}
|
||||
cookieStrings := make([]string, len(cookies))
|
||||
for i, cookie := range cookies {
|
||||
cookieStrings[i] = cookie.Name + "=" + cookie.Value
|
||||
}
|
||||
return strings.Join(cookieStrings, ";")
|
||||
}
|
||||
|
|
|
@ -6,8 +6,13 @@ import (
|
|||
)
|
||||
|
||||
type Addition struct {
|
||||
Type string `json:"type" type:"select" options:"cookie,url" default:"cookie"`
|
||||
Cookie string `json:"cookie" required:"true" help:"about 15 days valid, ignore if shareUrl is used"`
|
||||
Type string `json:"type" type:"select" options:"account,cookie,url" default:"cookie"`
|
||||
|
||||
Account string `json:"account"`
|
||||
Password string `json:"password"`
|
||||
|
||||
Cookie string `json:"cookie" help:"about 15 days valid, ignore if shareUrl is used"`
|
||||
|
||||
driver.RootID
|
||||
SharePassword string `json:"share_password"`
|
||||
BaseUrl string `json:"baseUrl" required:"true" default:"https://pc.woozooo.com" help:"basic URL for file operation"`
|
||||
|
@ -19,6 +24,10 @@ func (a *Addition) IsCookie() bool {
|
|||
return a.Type == "cookie"
|
||||
}
|
||||
|
||||
func (a *Addition) IsAccount() bool {
|
||||
return a.Type == "account"
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "Lanzou",
|
||||
LocalSort: true,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
var ErrFileShareCancel = errors.New("file sharing cancellation")
|
||||
var ErrFileNotExist = errors.New("file does not exist")
|
||||
var ErrCookieExpiration = errors.New("cookie expiration")
|
||||
|
||||
type RespText[T any] struct {
|
||||
Text T `json:"text"`
|
||||
|
|
|
@ -5,13 +5,16 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
@ -37,7 +40,24 @@ func (d *LanZou) get(url string, callback base.ReqCallback) ([]byte, error) {
|
|||
}
|
||||
|
||||
func (d *LanZou) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
return d._post(url, callback, resp, false)
|
||||
data, err := d._post(url, callback, resp, false)
|
||||
if err == ErrCookieExpiration && d.IsAccount() {
|
||||
if atomic.CompareAndSwapInt32(&d.flag, 0, 1) {
|
||||
_, err2 := d.Login()
|
||||
atomic.SwapInt32(&d.flag, 0)
|
||||
if err2 != nil {
|
||||
err = errors.Join(err, err2)
|
||||
d.Status = err.Error()
|
||||
op.MustSaveDriverStorage(d)
|
||||
return data, err
|
||||
}
|
||||
}
|
||||
for atomic.LoadInt32(&d.flag) != 0 {
|
||||
runtime.Gosched()
|
||||
}
|
||||
return d._post(url, callback, resp, false)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{}, up bool) ([]byte, error) {
|
||||
|
@ -49,10 +69,12 @@ func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{},
|
|||
}
|
||||
return false
|
||||
})
|
||||
callback(req)
|
||||
if callback != nil {
|
||||
callback(req)
|
||||
}
|
||||
}, up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return data, err
|
||||
}
|
||||
switch utils.Json.Get(data, "zt").ToInt() {
|
||||
case 1, 2, 4:
|
||||
|
@ -61,12 +83,14 @@ func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{},
|
|||
utils.Json.Unmarshal(data, resp)
|
||||
}
|
||||
return data, nil
|
||||
case 9: // 登录过期
|
||||
return data, ErrCookieExpiration
|
||||
default:
|
||||
info := utils.Json.Get(data, "inf").ToString()
|
||||
if info == "" {
|
||||
info = utils.Json.Get(data, "info").ToString()
|
||||
}
|
||||
return nil, fmt.Errorf(info)
|
||||
return data, fmt.Errorf(info)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +125,28 @@ func (d *LanZou) request(url string, method string, callback base.ReqCallback, u
|
|||
return res.Body(), err
|
||||
}
|
||||
|
||||
func (d *LanZou) Login() ([]*http.Cookie, error) {
|
||||
resp, err := base.NewRestyClient().SetRedirectPolicy(resty.NoRedirectPolicy()).
|
||||
R().SetFormData(map[string]string{
|
||||
"task": "3",
|
||||
"uid": d.Account,
|
||||
"pwd": d.Password,
|
||||
"setSessionId": "",
|
||||
"setSig": "",
|
||||
"setScene": "",
|
||||
"setTocen": "",
|
||||
"formhash": "",
|
||||
}).Post("https://up.woozooo.com/mlogin.php")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if utils.Json.Get(resp.Body(), "zt").ToInt() != 1 {
|
||||
return nil, fmt.Errorf("login err: %s", resp.Body())
|
||||
}
|
||||
d.Cookie = CookieToString(resp.Cookies())
|
||||
return resp.Cookies(), nil
|
||||
}
|
||||
|
||||
/*
|
||||
通过cookie获取数据
|
||||
*/
|
||||
|
@ -451,21 +497,32 @@ func (d *LanZou) getFileRealInfo(downURL string) (*int64, *time.Time) {
|
|||
return &size, &time
|
||||
}
|
||||
|
||||
func (d *LanZou) getVei() (string, error) {
|
||||
resp, err := d.get("https://pc.woozooo.com/mydisk.php", func(req *resty.Request) {
|
||||
func (d *LanZou) getVeiAndUid() (vei string, uid string, err error) {
|
||||
var resp []byte
|
||||
resp, err = d.get("https://pc.woozooo.com/mydisk.php", func(req *resty.Request) {
|
||||
req.SetQueryParams(map[string]string{
|
||||
"item": "files",
|
||||
"action": "index",
|
||||
"u": d.uid,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
return
|
||||
}
|
||||
// uid
|
||||
uids := regexp.MustCompile(`uid=([^'"&;]+)`).FindStringSubmatch(string(resp))
|
||||
if len(uids) < 2 {
|
||||
err = fmt.Errorf("uid variable not find")
|
||||
return
|
||||
}
|
||||
uid = uids[1]
|
||||
|
||||
// vei
|
||||
html := RemoveNotes(string(resp))
|
||||
data, err := htmlJsonToMap(html)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return
|
||||
}
|
||||
return data["vei"], nil
|
||||
vei = data["vei"]
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue