mirror of https://github.com/Xhofe/alist
				
				
				
			
		
			
				
	
	
		
			252 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
| package baidu_share
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| 	"path"
 | |
| 	"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/go-resty/resty/v2"
 | |
| )
 | |
| 
 | |
| type BaiduShare struct {
 | |
| 	model.Storage
 | |
| 	Addition
 | |
| 	client *resty.Client
 | |
| 	info   struct {
 | |
| 		Root    string
 | |
| 		Seckey  string
 | |
| 		Shareid string
 | |
| 		Uk      string
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Config() driver.Config {
 | |
| 	return config
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) GetAddition() driver.Additional {
 | |
| 	return &d.Addition
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Init(ctx context.Context) error {
 | |
| 	// TODO login / refresh token
 | |
| 	//op.MustSaveDriverStorage(d)
 | |
| 	d.client = resty.New().
 | |
| 		SetBaseURL("https://pan.baidu.com").
 | |
| 		SetHeader("User-Agent", "netdisk").
 | |
| 		SetCookie(&http.Cookie{Name: "BDUSS", Value: d.BDUSS}).
 | |
| 		SetCookie(&http.Cookie{Name: "ndut_fmt"})
 | |
| 	respJson := struct {
 | |
| 		Errno int64 `json:"errno"`
 | |
| 		Data  struct {
 | |
| 			List [1]struct {
 | |
| 				Path string `json:"path"`
 | |
| 			} `json:"list"`
 | |
| 			Uk      json.Number `json:"uk"`
 | |
| 			Shareid json.Number `json:"shareid"`
 | |
| 			Seckey  string      `json:"seckey"`
 | |
| 		} `json:"data"`
 | |
| 	}{}
 | |
| 	resp, err := d.client.R().
 | |
| 		SetBody(url.Values{
 | |
| 			"pwd":      {d.Pwd},
 | |
| 			"root":     {"1"},
 | |
| 			"shorturl": {d.Surl},
 | |
| 		}.Encode()).
 | |
| 		SetResult(&respJson).
 | |
| 		Post("share/wxlist?channel=weixin&version=2.2.2&clienttype=25&web=1")
 | |
| 	if err == nil {
 | |
| 		if resp.IsSuccess() && respJson.Errno == 0 {
 | |
| 			d.info.Root = path.Dir(respJson.Data.List[0].Path)
 | |
| 			d.info.Seckey = respJson.Data.Seckey
 | |
| 			d.info.Shareid = respJson.Data.Shareid.String()
 | |
| 			d.info.Uk = respJson.Data.Uk.String()
 | |
| 		} else {
 | |
| 			err = fmt.Errorf(" %s; %s; ", resp.Status(), resp.Body())
 | |
| 		}
 | |
| 	}
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Drop(ctx context.Context) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
 | |
| 	// TODO return the files list, required
 | |
| 	reqDir := dir.GetPath()
 | |
| 	isRoot := "0"
 | |
| 	if reqDir == d.RootFolderPath {
 | |
| 		reqDir = path.Join(d.info.Root, reqDir)
 | |
| 	}
 | |
| 	if reqDir == d.info.Root {
 | |
| 		isRoot = "1"
 | |
| 	}
 | |
| 	objs := []model.Obj{}
 | |
| 	var err error
 | |
| 	var page uint64 = 1
 | |
| 	more := true
 | |
| 	for more && err == nil {
 | |
| 		respJson := struct {
 | |
| 			Errno int64 `json:"errno"`
 | |
| 			Data  struct {
 | |
| 				More bool `json:"has_more"`
 | |
| 				List []struct {
 | |
| 					Fsid  json.Number `json:"fs_id"`
 | |
| 					Isdir json.Number `json:"isdir"`
 | |
| 					Path  string      `json:"path"`
 | |
| 					Name  string      `json:"server_filename"`
 | |
| 					Mtime json.Number `json:"server_mtime"`
 | |
| 					Size  json.Number `json:"size"`
 | |
| 				} `json:"list"`
 | |
| 			} `json:"data"`
 | |
| 		}{}
 | |
| 		resp, e := d.client.R().
 | |
| 			SetBody(url.Values{
 | |
| 				"dir":      {reqDir},
 | |
| 				"num":      {"1000"},
 | |
| 				"order":    {"time"},
 | |
| 				"page":     {fmt.Sprint(page)},
 | |
| 				"pwd":      {d.Pwd},
 | |
| 				"root":     {isRoot},
 | |
| 				"shorturl": {d.Surl},
 | |
| 			}.Encode()).
 | |
| 			SetResult(&respJson).
 | |
| 			Post("share/wxlist?channel=weixin&version=2.2.2&clienttype=25&web=1")
 | |
| 		err = e
 | |
| 		if err == nil {
 | |
| 			if resp.IsSuccess() && respJson.Errno == 0 {
 | |
| 				page++
 | |
| 				more = respJson.Data.More
 | |
| 				for _, v := range respJson.Data.List {
 | |
| 					size, _ := v.Size.Int64()
 | |
| 					mtime, _ := v.Mtime.Int64()
 | |
| 					objs = append(objs, &model.Object{
 | |
| 						ID:       v.Fsid.String(),
 | |
| 						Path:     v.Path,
 | |
| 						Name:     v.Name,
 | |
| 						Size:     size,
 | |
| 						Modified: time.Unix(mtime, 0),
 | |
| 						IsFolder: v.Isdir.String() == "1",
 | |
| 					})
 | |
| 				}
 | |
| 			} else {
 | |
| 				err = fmt.Errorf(" %s; %s; ", resp.Status(), resp.Body())
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return objs, err
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
 | |
| 	// TODO return link of file, required
 | |
| 	link := model.Link{Header: d.client.Header}
 | |
| 	sign := ""
 | |
| 	stamp := ""
 | |
| 	signJson := struct {
 | |
| 		Errno int64 `json:"errno"`
 | |
| 		Data  struct {
 | |
| 			Stamp json.Number `json:"timestamp"`
 | |
| 			Sign  string      `json:"sign"`
 | |
| 		} `json:"data"`
 | |
| 	}{}
 | |
| 	resp, err := d.client.R().
 | |
| 		SetQueryParam("surl", d.Surl).
 | |
| 		SetResult(&signJson).
 | |
| 		Get("share/tplconfig?fields=sign,timestamp&channel=chunlei&web=1&app_id=250528&clienttype=0")
 | |
| 	if err == nil {
 | |
| 		if resp.IsSuccess() && signJson.Errno == 0 {
 | |
| 			stamp = signJson.Data.Stamp.String()
 | |
| 			sign = signJson.Data.Sign
 | |
| 		} else {
 | |
| 			err = fmt.Errorf(" %s; %s; ", resp.Status(), resp.Body())
 | |
| 		}
 | |
| 	}
 | |
| 	if err == nil {
 | |
| 		respJson := struct {
 | |
| 			Errno int64 `json:"errno"`
 | |
| 			List  [1]struct {
 | |
| 				Dlink string `json:"dlink"`
 | |
| 			} `json:"list"`
 | |
| 		}{}
 | |
| 		resp, err = d.client.R().
 | |
| 			SetQueryParam("sign", sign).
 | |
| 			SetQueryParam("timestamp", stamp).
 | |
| 			SetBody(url.Values{
 | |
| 				"encrypt":   {"0"},
 | |
| 				"extra":     {fmt.Sprintf(`{"sekey":"%s"}`, d.info.Seckey)},
 | |
| 				"fid_list":  {fmt.Sprintf("[%s]", file.GetID())},
 | |
| 				"primaryid": {d.info.Shareid},
 | |
| 				"product":   {"share"},
 | |
| 				"type":      {"nolimit"},
 | |
| 				"uk":        {d.info.Uk},
 | |
| 			}.Encode()).
 | |
| 			SetResult(&respJson).
 | |
| 			Post("api/sharedownload?app_id=250528&channel=chunlei&clienttype=12&web=1")
 | |
| 		if err == nil {
 | |
| 			if resp.IsSuccess() && respJson.Errno == 0 && respJson.List[0].Dlink != "" {
 | |
| 				link.URL = respJson.List[0].Dlink
 | |
| 			} else {
 | |
| 				err = fmt.Errorf(" %s; %s; ", resp.Status(), resp.Body())
 | |
| 			}
 | |
| 		}
 | |
| 		if err == nil {
 | |
| 			resp, err = d.client.R().
 | |
| 				SetDoNotParseResponse(true).
 | |
| 				Get(link.URL)
 | |
| 			if err == nil {
 | |
| 				defer resp.RawBody().Close()
 | |
| 				if resp.IsError() {
 | |
| 					byt, _ := io.ReadAll(resp.RawBody())
 | |
| 					err = fmt.Errorf(" %s; %s; ", resp.Status(), byt)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return &link, err
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
 | |
| 	// TODO create folder, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
 | |
| 	// TODO move obj, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
 | |
| 	// TODO rename obj, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
 | |
| 	// TODO copy obj, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Remove(ctx context.Context, obj model.Obj) error {
 | |
| 	// TODO remove obj, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| func (d *BaiduShare) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
 | |
| 	// TODO upload file, optional
 | |
| 	return errs.NotSupport
 | |
| }
 | |
| 
 | |
| //func (d *Template) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
 | |
| //	return nil, errs.NotSupport
 | |
| //}
 | |
| 
 | |
| var _ driver.Driver = (*BaiduShare)(nil)
 |