学习通下载器 Chaoxing Downloader

一键下载资料文件,无视系统限制。

Installera detta skript?
Författaren's rekommenderade skript

Du kanske också gillar 学习通/MOOC等 隐藏答案 Hide Answer.

Installera detta skript
// ==UserScript==
// @name         学习通下载器 Chaoxing Downloader
// @namespace    https://github.com/lcandy2/user.js/tree/main/websites/chaoxing.com/chaoxing-downloader
// @version      1.2
// @author       甜檸Cirtron (lcandy2)
// @description  一键下载资料文件,无视系统限制。
// @license      AGPL-3.0-or-later
// @copyright    lcandy2 All Rights Reserved
// @homepage     https://greasyfork.org/scripts/499214
// @homepageURL  https://greasyfork.org/scripts/499214
// @source       https://github.com/lcandy2/user.js/tree/main/websites/chaoxing.com/chaoxing-downloader
// @match        *://*.chaoxing.com/mooc2-ans/coursedata/stu-datalist*
// @require      https://registry.npmmirror.com/vue/3.4.27/files/dist/vue.global.prod.js
// @require      data:application/javascript,%3Bwindow.Vue%3DVue%3B
// @require      https://registry.npmmirror.com/vuetify/3.6.6/files/dist/vuetify.min.js
// @require      data:application/javascript,%3B
// @resource     VuetifyStyle  https://registry.npmmirror.com/vuetify/3.6.6/files/dist/vuetify.min.css
// @connect      pan-yz.chaoxing.com
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_xmlhttpRequest
// @run-at       document-end
// ==/UserScript==

(function (vue, vuetify) {
  'use strict';

  var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  const backgroundFetch = async (url) => {
    return new Promise((resolve, reject) => {
      _GM_xmlhttpRequest({
        method: "GET",
        url,
        onload: (response) => {
          resolve(response.responseText);
        },
        onerror: (error) => {
          reject(error);
        }
      });
    });
  };
  const _sfc_main = /* @__PURE__ */ vue.defineComponent({
    __name: "App",
    setup(__props) {
      const buttonRef = vue.ref(null);
      const downloadLink = vue.ref("");
      const isDownloading = vue.ref(false);
      const isFinished = vue.ref(false);
      const isErrored = vue.ref(false);
      const fileInfo = vue.ref({
        fileName: "",
        objectId: "",
        dataId: "",
        t: "",
        courseId: "",
        clazzId: "",
        cpi: "",
        puid: ""
      });
      const handleClick = async (event) => {
        !isFinished.value && event.preventDefault();
        isDownloading.value = true;
        if (buttonRef.value && !isFinished.value) {
          try {
            const tokenReq = await backgroundFetch("https://pan-yz.chaoxing.com/api/token/uservalid");
            const tokenJson = JSON.parse(tokenReq);
            const token = tokenJson._token;
            const fileInfoApi = new URL(
              "https://pan-yz.chaoxing.com/api/share/downloadUrl"
            );
            fileInfoApi.searchParams.set("puid", fileInfo.value.puid);
            fileInfoApi.searchParams.set("_token", token);
            fileInfoApi.searchParams.set("sarepuid", fileInfo.value.puid);
            fileInfoApi.searchParams.set("objectid", fileInfo.value.objectId);
            const fileInfoReq = await backgroundFetch(fileInfoApi.toString());
            const fileInfoJson = JSON.parse(fileInfoReq);
            const fileInfoUrl = fileInfoJson.url;
            downloadLink.value = fileInfoUrl.toString();
            isFinished.value = true;
            vue.nextTick(() => {
              buttonRef.value.$el.click();
            });
          } catch (e) {
            isErrored.value = true;
            console.error(e);
          }
        } else {
          isDownloading.value = false;
        }
      };
      vue.onMounted(() => {
        var _a;
        if (buttonRef.value) {
          try {
            const fileElement = (_a = buttonRef.value.$el.parentElement) == null ? void 0 : _a.parentElement.parentElement.parentElement;
            fileInfo.value.objectId = fileElement == null ? void 0 : fileElement.getAttribute("objectid");
            fileInfo.value.fileName = fileElement == null ? void 0 : fileElement.getAttribute("dataname");
            fileInfo.value.dataId = (fileElement == null ? void 0 : fileElement.getAttribute("id")) || (fileElement == null ? void 0 : fileElement.getAttribute("order"));
            fileInfo.value.t = fileElement == null ? void 0 : fileElement.getAttribute("t");
            const userIdElement = document.querySelector("input#userId");
            if (userIdElement) {
              fileInfo.value.puid = userIdElement.getAttribute("value") || "";
            }
            const href = new URL(window.location.href);
            fileInfo.value.courseId = href.searchParams.get("courseid") || "";
            fileInfo.value.clazzId = href.searchParams.get("clazzid") || "";
            fileInfo.value.cpi = href.searchParams.get("cpi") || "";
            const downloadUrl = new URL(
              "https://mooc1.chaoxing.com/coursedata/downloadData?ut=s"
            );
            downloadUrl.searchParams.set("dataId", fileInfo.value.dataId);
            downloadUrl.searchParams.set("classId", fileInfo.value.clazzId);
            downloadUrl.searchParams.set("cpi", fileInfo.value.cpi);
            downloadUrl.searchParams.set("courseId", fileInfo.value.courseId);
            downloadLink.value = downloadUrl.toString();
          } catch (e) {
            isErrored.value = true;
            console.error(e);
          }
        }
      });
      return (_ctx, _cache) => {
        const _component_v_btn = vue.resolveComponent("v-btn");
        return vue.openBlock(), vue.createBlock(_component_v_btn, {
          ref_key: "buttonRef",
          ref: buttonRef,
          disabled: isErrored.value,
          loading: isDownloading.value && !isErrored.value,
          onClick: handleClick,
          href: downloadLink.value,
          density: "compact",
          variant: "plain",
          color: "primary"
        }, {
          default: vue.withCtx(() => [
            vue.createTextVNode(vue.toDisplayString(isErrored.value ? "下载器错误,请刷新重试" : isDownloading.value ? "正在下载中" : isFinished.value ? "下载完成" : "下载器下载"), 1)
          ]),
          _: 1
        }, 8, ["disabled", "loading", "href"]);
      };
    }
  });
  const appendApp = (element) => {
    const vuetify$1 = vuetify.createVuetify({});
    const app = vue.createApp(_sfc_main);
    app.use(vuetify$1);
    app.mount(element);
  };
  const cssLoader = (e) => {
    const t = GM_getResourceText(e);
    return GM_addStyle(t), t;
  };
  cssLoader("VuetifyStyle");
  function addElement() {
    const uls = document.querySelectorAll("ul.operate");
    uls.forEach((ul) => {
      var _a;
      const file = (_a = ul.parentElement) == null ? void 0 : _a.parentElement;
      if (!file)
        return;
      const isBook = file.getAttribute("type") === "book";
      const isAFolder = file.getAttribute("type") === "afolder";
      const hasObjectID = file.getAttribute("objectid") !== "";
      if (isBook || isAFolder || !hasObjectID)
        return;
      if (!ul.querySelector("[chaoxing-downloader]")) {
        const li = document.createElement("li");
        li.className = "operate_down";
        li.setAttribute("chaoxing-downloader", "");
        ul.appendChild(li);
        appendApp(li);
      }
    });
  }
  addElement();
  const observer = new MutationObserver((mutationsList, observer2) => {
    for (let mutation of mutationsList) {
      if (mutation.type === "childList") {
        addElement();
      }
    }
  });
  const config = { childList: true, subtree: true };
  observer.observe(document, config);

})(Vue, Vuetify);