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 }