github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/baidupcs/transfer.go (about)

     1  package baidupcs
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/qjfoidnh/BaiduPCS-Go/requester"
     6  	"github.com/tidwall/gjson"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/url"
    10  	"path"
    11  	"path/filepath"
    12  	"regexp"
    13  	"strconv"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  type (
    19  	// ShareOption 分享可选项
    20  	TransferOption struct {
    21  		Download bool // 是否直接开始下载
    22  		Collect  bool // 多文件整合
    23  		Rname    bool // 随机改文件名
    24  	}
    25  )
    26  
    27  func (pcs *BaiduPCS) GenerateShareQueryURL(subPath string, params map[string]string) *url.URL {
    28  	shareURL := &url.URL{
    29  		Scheme: GetHTTPScheme(true),
    30  		Host:   PanBaiduCom,
    31  		Path:   "/share/" + subPath,
    32  	}
    33  	uv := shareURL.Query()
    34  	uv.Set("app_id", PanAppID)
    35  	uv.Set("channel", "chunlei")
    36  	uv.Set("t", strconv.Itoa(int(time.Now().UnixMilli())))
    37  	uv.Set("web", "1")
    38  	uv.Set("clienttype", "0")
    39  	for key, value := range params {
    40  		uv.Set(key, value)
    41  	}
    42  
    43  	shareURL.RawQuery = uv.Encode()
    44  	return shareURL
    45  }
    46  
    47  func (pcs *BaiduPCS) ExtractShareInfo(metajsonstr string) (res map[string]string) {
    48  	res = make(map[string]string)
    49  	if !strings.Contains(metajsonstr, "server_filename") {
    50  		res["ErrMsg"] = "获取分享文件详情失败"
    51  		return
    52  	}
    53  	errno := gjson.Get(metajsonstr, `file_list.errno`).Int()
    54  	if errno != 0 {
    55  		res["ErrMsg"] = fmt.Sprintf("未知错误, 错误码%d", errno)
    56  		return
    57  	}
    58  	res["filename"] = gjson.Get(metajsonstr, `file_list.0.server_filename`).String()
    59  	fsid_list := gjson.Get(metajsonstr, `file_list.#.fs_id`).Array()
    60  	var fids_str string = "["
    61  	for _, sid := range fsid_list {
    62  		fids_str += sid.String() + ","
    63  	}
    64  
    65  	res["shareid"] = gjson.Get(metajsonstr, `shareid`).String()
    66  	res["from"] = gjson.Get(metajsonstr, `share_uk`).String()
    67  	res["bdstoken"] = gjson.Get(metajsonstr, `bdstoken`).String()
    68  	shareUrl := &url.URL{
    69  		Scheme: GetHTTPScheme(true),
    70  		Host:   PanBaiduCom,
    71  		Path:   "/share/transfer",
    72  	}
    73  	uv := shareUrl.Query()
    74  	uv.Set("app_id", PanAppID)
    75  	uv.Set("channel", "chunlei")
    76  	uv.Set("clienttype", "0")
    77  	uv.Set("web", "1")
    78  	for key, value := range res {
    79  		uv.Set(key, value)
    80  	}
    81  	res["item_num"] = strconv.Itoa(len(fsid_list))
    82  	res["ErrMsg"] = "0"
    83  	res["fs_id"] = fids_str[:len(fids_str)-1] + "]"
    84  	shareUrl.RawQuery = uv.Encode()
    85  	res["shareUrl"] = shareUrl.String()
    86  	return
    87  }
    88  
    89  func (pcs *BaiduPCS) PostShareQuery(url string, referer string, data map[string]string) (res map[string]string) {
    90  	dataReadCloser, panError := pcs.sendReqReturnReadCloser(reqTypePan, OperationShareFileSavetoLocal, http.MethodPost, url, data, map[string]string{
    91  		"User-Agent":   requester.UserAgent,
    92  		"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    93  		"Referer": referer,
    94  	})
    95  	res = make(map[string]string)
    96  	if panError != nil {
    97  		res["ErrMsg"] = "提交分享项查询请求时发生错误"
    98  		return
    99  	}
   100  	defer dataReadCloser.Close()
   101  	body, _ := ioutil.ReadAll(dataReadCloser)
   102  	errno := gjson.Get(string(body), `errno`).Int()
   103  	if errno != 0 {
   104  		res["ErrMsg"] = fmt.Sprintf("未知错误, 错误码%d", errno)
   105  		if errno == -9 {
   106  			res["ErrMsg"] = "提取码错误"
   107  		}
   108  		return
   109  	}
   110  	res["ErrMsg"] = "0"
   111  	return
   112  }
   113  
   114  func (pcs *BaiduPCS) AccessSharePage(featurestr string, first bool) (tokens map[string]string) {
   115  	tokens = make(map[string]string)
   116  	tokens["ErrMsg"] = "0"
   117  	headers := make(map[string]string)
   118  	headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
   119  	headers["Referer"] = "https://pan.baidu.com/disk/home"
   120  	if !first {
   121  		headers["Referer"] = fmt.Sprintf("https://pan.baidu.com/share/init?surl=%s", featurestr[1:])
   122  	}
   123  	sharelink := fmt.Sprintf("https://pan.baidu.com/s/%s", featurestr)
   124  
   125  	dataReadCloser, panError := pcs.sendReqReturnReadCloser(reqTypePan, OperationShareFileSavetoLocal, http.MethodGet, sharelink, nil, headers)
   126  
   127  	if panError != nil {
   128  		tokens["ErrMsg"] = "访问分享页失败"
   129  		return
   130  	}
   131  	defer dataReadCloser.Close()
   132  	body, _ := ioutil.ReadAll(dataReadCloser)
   133  	not_found_flag := strings.Contains(string(body), "platform-non-found")
   134  	error_page_title := strings.Contains(string(body), "error-404")
   135  	if error_page_title {
   136  		tokens["ErrMsg"] = "页面不存在"
   137  		return
   138  	}
   139  	if not_found_flag {
   140  		tokens["ErrMsg"] = "分享链接已失效"
   141  		return
   142  	} else {
   143  		re, _ := regexp.Compile(`(\{.+?loginstate.+?\})\);`)
   144  		sub := re.FindSubmatch(body)
   145  		if len(sub) < 2 {
   146  			tokens["ErrMsg"] = "请确认登录参数中已经包含了网盘STOKEN"
   147  			return
   148  		}
   149  		tokens["metajson"] = string(sub[1])
   150  		tokens["bdstoken"] = gjson.Get(string(sub[1]), `bdstoken`).String()
   151  		tokens["uk"] = gjson.Get(string(sub[1]), `uk`).String()
   152  		tokens["share_uk"] = gjson.Get(string(sub[1]), `share_uk`).String()
   153  		tokens["shareid"] = gjson.Get(string(sub[1]), `shareid`).String()
   154  		return
   155  	}
   156  
   157  }
   158  
   159  func (pcs *BaiduPCS) GenerateRequestQuery(mode string, params map[string]string) (res map[string]string) {
   160  	res = make(map[string]string)
   161  	res["ErrNo"] = "0"
   162  	headers := map[string]string{
   163  		"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
   164  		"Referer":    params["referer"],
   165  	}
   166  	if mode == "POST" {
   167  		headers["Content-Type"] = "application/x-www-form-urlencoded"
   168  	}
   169  	postdata := make(map[string]string)
   170  	postdata["fsidlist"] = params["fs_id"]
   171  	postdata["path"] = params["path"]
   172  	dataReadCloser, panError := pcs.sendReqReturnReadCloser(reqTypePan, OperationShareFileSavetoLocal, mode, params["shareUrl"], postdata, headers)
   173  	if panError != nil {
   174  		res["ErrNo"] = "1"
   175  		res["ErrMsg"] = "网络错误"
   176  		return
   177  	}
   178  	defer dataReadCloser.Close()
   179  	body, err := ioutil.ReadAll(dataReadCloser)
   180  	if err != nil {
   181  		res["ErrNo"] = "-1"
   182  		res["ErrMsg"] = "未知错误"
   183  		return
   184  	}
   185  	if !gjson.Valid(string(body)) {
   186  		res["ErrNo"] = "2"
   187  		res["ErrMsg"] = "返回json解析错误"
   188  		return
   189  	}
   190  	errno := gjson.Get(string(body), `errno`).Int()
   191  	if errno != 0 {
   192  		res["ErrNo"] = "3"
   193  		res["ErrMsg"] = "获取分享项元数据错误"
   194  		if mode == "POST" && errno == 12 {
   195  			path := gjson.Get(string(body), `info.0.path`).String()
   196  			_, file := filepath.Split(path) // Should be path.Split here, but never mind~
   197  			_errno := gjson.Get(string(body), `info.0.errno`).Int()
   198  			target_file_nums := gjson.Get(string(body), `target_file_nums`).Int()
   199  			target_file_nums_limit := gjson.Get(string(body), `target_file_nums_limit`).Int()
   200  			if target_file_nums > target_file_nums_limit {
   201  				res["ErrNo"] = "4"
   202  				res["ErrMsg"] = fmt.Sprintf("转存文件数%d超过当前用户上限, 当前用户单次最大转存数%d", target_file_nums, target_file_nums_limit)
   203  				res["limit"] = fmt.Sprintf("%d", target_file_nums_limit)
   204  			} else if _errno == -30 {
   205  				res["ErrNo"] = "9"
   206  				res["ErrMsg"] = fmt.Sprintf("当前目录下已有%s同名文件/文件夹", file)
   207  			} else {
   208  				res["ErrMsg"] = fmt.Sprintf("未知错误, 错误代码%d", _errno)
   209  			}
   210  		} else if mode == "POST" && errno == 4 {
   211  			res["ErrMsg"] = fmt.Sprintf("文件重复")
   212  		}
   213  		return
   214  	}
   215  	_, res["filename"] = filepath.Split(gjson.Get(string(body), `info.0.path`).String())
   216  	filenames := gjson.Get(string(body), `info.#.path`).Array()
   217  	filenames_str := ""
   218  	for _, _path := range filenames {
   219  		filenames_str += "," + path.Base(_path.String())
   220  	}
   221  	res["filenames"] = filenames_str[1:]
   222  	if len(gjson.Get(string(body), `info.#.fsid`).Array()) > 1 {
   223  		res["filename"] += "等多个文件/文件夹"
   224  	}
   225  	return
   226  }
   227  
   228  func (pcs *BaiduPCS) SuperTransfer(params map[string]string, limit string) {
   229  	//headers := map[string]string{
   230  	//	"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
   231  	//	"Referer":    params["referer"],
   232  	//}
   233  	//limit_num, _ := strconv.Atoi(limit)
   234  	//fsidlist_str := params["fs_id"]
   235  	//fsidlist := strings.Split(fsidlist_str[1:len(fsidlist_str)-1], ",")
   236  	//listUrl := &url.URL{
   237  	//	Scheme: GetHTTPScheme(true),
   238  	//	Host:   PanBaiduCom,
   239  	//	Path:   "/share/list",
   240  	//}
   241  	//uv := listUrl.Query()
   242  	//uv.Set("app_id", PanAppID)
   243  	//uv.Set("channel", "chunlei")
   244  	//uv.Set("clienttype", "0")
   245  	//uv.Set("web", "1")
   246  	//uv.Set("page", "1")
   247  	//uv.Set("num", "100")
   248  	//uv.Set("shorturl", params["shorturl"])
   249  	//uv.Set("root", "1")
   250  	//dataReadCloser, panError := pcs.sendReqReturnReadCloser(reqTypePan, OperationShareFileSavetoLocal, http.MethodGet, listUrl.String(), nil, headers)
   251  	//if panError != nil {
   252  	//	res["ErrNo"] = "1"
   253  	//	res["ErrMsg"] = "网络错误"
   254  	//	return
   255  	//}
   256  	//defer dataReadCloser.Close()
   257  	//body, err := ioutil.ReadAll(dataReadCloser)
   258  	//res["ErrNo"] = "-1"
   259  	//if err != nil {
   260  	//	res["ErrMsg"] = "未知错误"
   261  	//	return
   262  	//}
   263  	return
   264  
   265  }