mirror of https://github.com/Xhofe/alist
parent
9f08353d31
commit
c9ea9bce81
|
@ -2,9 +2,7 @@ package lanzou
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
@ -19,6 +17,8 @@ type LanZou struct {
|
||||||
model.Storage
|
model.Storage
|
||||||
uid string
|
uid string
|
||||||
vei string
|
vei string
|
||||||
|
|
||||||
|
flag int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) Config() driver.Config {
|
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) {
|
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 == "" {
|
if d.RootFolderID == "" {
|
||||||
d.RootFolderID = "-1"
|
d.RootFolderID = "-1"
|
||||||
}
|
}
|
||||||
ylogin := regexp.MustCompile("ylogin=(.*?);").FindStringSubmatch(d.Cookie)
|
d.vei, d.uid, err = d.getVeiAndUid()
|
||||||
if len(ylogin) < 2 {
|
|
||||||
return fmt.Errorf("cookie does not contain ylogin")
|
|
||||||
}
|
|
||||||
d.uid = ylogin[1]
|
|
||||||
d.vei, err = d.getVei()
|
|
||||||
}
|
}
|
||||||
return
|
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) {
|
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())
|
return d.GetAllFiles(dir.GetID())
|
||||||
} else {
|
} else {
|
||||||
return d.GetFileOrFolderByShareUrl(dir.GetID(), d.SharePassword)
|
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) {
|
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) {
|
data, err := d.doupload(func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
req.SetFormData(map[string]string{
|
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(),
|
FolID: utils.Json.Get(data, "text").ToString(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
return nil, errs.NotImplement
|
return nil, errs.NotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
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() {
|
if !srcObj.IsDir() {
|
||||||
_, err := d.doupload(func(req *resty.Request) {
|
_, err := d.doupload(func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
|
@ -157,11 +159,11 @@ func (d *LanZou) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj,
|
||||||
return srcObj, nil
|
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) {
|
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() {
|
if !srcObj.IsDir() {
|
||||||
_, err := d.doupload(func(req *resty.Request) {
|
_, err := d.doupload(func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
|
@ -179,11 +181,11 @@ func (d *LanZou) Rename(ctx context.Context, srcObj model.Obj, newName string) (
|
||||||
return srcObj, nil
|
return srcObj, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errs.NotImplement
|
return nil, errs.NotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) Remove(ctx context.Context, obj model.Obj) error {
|
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) {
|
_, err := d.doupload(func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
if obj.IsDir() {
|
if obj.IsDir() {
|
||||||
|
@ -200,13 +202,13 @@ func (d *LanZou) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
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) {
|
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]
|
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{
|
req.SetFormData(map[string]string{
|
||||||
"task": "1",
|
"task": "1",
|
||||||
"vie": "2",
|
"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 &resp.Text[0], nil
|
||||||
}
|
}
|
||||||
return nil, errs.NotImplement
|
return nil, errs.NotSupport
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package lanzou
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -190,3 +191,14 @@ func GetExpirationTime(url string) (etime time.Duration) {
|
||||||
etime = time.Duration(timestamp-time.Now().Unix()) * time.Second
|
etime = time.Duration(timestamp-time.Now().Unix()) * time.Second
|
||||||
return
|
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 Addition struct {
|
||||||
Type string `json:"type" type:"select" options:"cookie,url" default:"cookie"`
|
Type string `json:"type" type:"select" options:"account,cookie,url" default:"cookie"`
|
||||||
Cookie string `json:"cookie" required:"true" help:"about 15 days valid, ignore if shareUrl is used"`
|
|
||||||
|
Account string `json:"account"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
|
||||||
|
Cookie string `json:"cookie" help:"about 15 days valid, ignore if shareUrl is used"`
|
||||||
|
|
||||||
driver.RootID
|
driver.RootID
|
||||||
SharePassword string `json:"share_password"`
|
SharePassword string `json:"share_password"`
|
||||||
BaseUrl string `json:"baseUrl" required:"true" default:"https://pc.woozooo.com" help:"basic URL for file operation"`
|
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"
|
return a.Type == "cookie"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Addition) IsAccount() bool {
|
||||||
|
return a.Type == "account"
|
||||||
|
}
|
||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
Name: "Lanzou",
|
Name: "Lanzou",
|
||||||
LocalSort: true,
|
LocalSort: true,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
var ErrFileShareCancel = errors.New("file sharing cancellation")
|
var ErrFileShareCancel = errors.New("file sharing cancellation")
|
||||||
var ErrFileNotExist = errors.New("file does not exist")
|
var ErrFileNotExist = errors.New("file does not exist")
|
||||||
|
var ErrCookieExpiration = errors.New("cookie expiration")
|
||||||
|
|
||||||
type RespText[T any] struct {
|
type RespText[T any] struct {
|
||||||
Text T `json:"text"`
|
Text T `json:"text"`
|
||||||
|
|
|
@ -5,13 +5,16 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -37,8 +40,25 @@ func (d *LanZou) get(url string, callback base.ReqCallback) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
func (d *LanZou) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
|
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 d._post(url, callback, resp, false)
|
||||||
}
|
}
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{}, up bool) ([]byte, error) {
|
func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{}, up bool) ([]byte, error) {
|
||||||
data, err := d.request(url, http.MethodPost, func(req *resty.Request) {
|
data, err := d.request(url, http.MethodPost, func(req *resty.Request) {
|
||||||
|
@ -49,10 +69,12 @@ func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{},
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
if callback != nil {
|
||||||
callback(req)
|
callback(req)
|
||||||
|
}
|
||||||
}, up)
|
}, up)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return data, err
|
||||||
}
|
}
|
||||||
switch utils.Json.Get(data, "zt").ToInt() {
|
switch utils.Json.Get(data, "zt").ToInt() {
|
||||||
case 1, 2, 4:
|
case 1, 2, 4:
|
||||||
|
@ -61,12 +83,14 @@ func (d *LanZou) _post(url string, callback base.ReqCallback, resp interface{},
|
||||||
utils.Json.Unmarshal(data, resp)
|
utils.Json.Unmarshal(data, resp)
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
|
case 9: // 登录过期
|
||||||
|
return data, ErrCookieExpiration
|
||||||
default:
|
default:
|
||||||
info := utils.Json.Get(data, "inf").ToString()
|
info := utils.Json.Get(data, "inf").ToString()
|
||||||
if info == "" {
|
if info == "" {
|
||||||
info = utils.Json.Get(data, "info").ToString()
|
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
|
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获取数据
|
通过cookie获取数据
|
||||||
*/
|
*/
|
||||||
|
@ -451,21 +497,32 @@ func (d *LanZou) getFileRealInfo(downURL string) (*int64, *time.Time) {
|
||||||
return &size, &time
|
return &size, &time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) getVei() (string, error) {
|
func (d *LanZou) getVeiAndUid() (vei string, uid string, err error) {
|
||||||
resp, err := d.get("https://pc.woozooo.com/mydisk.php", func(req *resty.Request) {
|
var resp []byte
|
||||||
|
resp, err = d.get("https://pc.woozooo.com/mydisk.php", func(req *resty.Request) {
|
||||||
req.SetQueryParams(map[string]string{
|
req.SetQueryParams(map[string]string{
|
||||||
"item": "files",
|
"item": "files",
|
||||||
"action": "index",
|
"action": "index",
|
||||||
"u": d.uid,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if err != nil {
|
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))
|
html := RemoveNotes(string(resp))
|
||||||
data, err := htmlJsonToMap(html)
|
data, err := htmlJsonToMap(html)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return
|
||||||
}
|
}
|
||||||
return data["vei"], nil
|
vei = data["vei"]
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue