万门大学课程视频批量下载

只能批量下载免费的或者已经购买的课程

// ==UserScript==
// @name         万门大学课程视频批量下载
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  只能批量下载免费的或者已经购买的课程
// @author       none
// @match        https://www.wanmen.org/courses/*
// @grant        none
// ==/UserScript==

// 本文件由 src/index.ts 生成,请修改 src/index.ts 后执行 yarn build 生成,勿直接修改此文件。

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
function getChapterElements() {
    return document.querySelector("#root > div.course__course-page--3J8Sy > div.course__video-row--20SaE > div.course__playlist-container--17tSE > div.components__container--1fgQp > div > div:nth-child(1) > ul");
}
function checkClientStatus() {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            let response = yield fetch("http://localhost:5678/status", {
                method: "get",
                mode: "cors",
            });
            if (!response.ok) {
                throw Error(response.statusText);
            }
            return true;
        }
        catch (error) {
            alert("客户端未启动,请启动客户端之后再开始");
            return false;
        }
    });
}
function sleep(ms) {
    return __awaiter(this, void 0, void 0, function* () {
        return new Promise((resolve) => setTimeout(resolve, ms));
    });
}
function waitValue({ predicate, waitInterval, timeout, timeoutRetry, }) {
    return __awaiter(this, void 0, void 0, function* () {
        let value = null;
        let waitTime = 0;
        do {
            value = yield predicate();
            yield sleep(waitInterval);
            waitTime += waitInterval;
            if (typeof timeout !== "undefined" && waitTime >= timeout) {
                timeoutRetry === null || timeoutRetry === void 0 ? void 0 : timeoutRetry();
                waitTime = 0;
            }
        } while (!value);
        return value;
    });
}
function addTask() {
    return __awaiter(this, void 0, void 0, function* () {
        if (!(yield checkClientStatus())) {
            return;
        }
        const cptEles = getChapterElements();
        if (!cptEles) {
            alert("未获取到课程列表");
            return;
        }
        const courseName = prompt("请输入课程名称", document.title);
        if (!courseName) {
            alert("课程名称不能为空");
            return;
        }
        const chapters = [];
        for (let chapterElement = cptEles.firstElementChild, cptIdx = 1; chapterElement; chapterElement = chapterElement.nextElementSibling, cptIdx++) {
            const subChapterTitle = chapterElement.querySelector("div");
            if (!subChapterTitle) {
                continue;
            }
            if (subChapterTitle.className.indexOf("presentation") < 0) {
                subChapterTitle.click();
            }
            else {
                continue;
            }
            const subChapters = yield waitValue({
                predicate: () => __awaiter(this, void 0, void 0, function* () { return chapterElement.querySelector("ul"); }),
                waitInterval: 50,
                timeout: 2000,
                timeoutRetry: () => subChapterTitle.click(),
            });
            for (let subCptEle = subChapters.firstElementChild; subCptEle; subCptEle = subCptEle.nextElementSibling) {
                const anchor = subCptEle.querySelector("a");
                if (anchor) {
                    chapters.push({
                        Link: anchor.href,
                        Name: anchor.innerText.split("\n")[0],
                    });
                }
            }
            subChapterTitle.click();
        }
        try {
            let addResponse = yield fetch("http://localhost:5678/add", {
                method: "post",
                mode: "cors",
                body: JSON.stringify({
                    Name: courseName,
                    chapters,
                }),
            });
            if (!addResponse.ok) {
                throw new Error(addResponse.statusText);
            }
        }
        catch (error) {
            alert("已将任务发送到客户端,处理中...");
        }
    });
}
function getM3u8Source() {
    var _a;
    return __awaiter(this, void 0, void 0, function* () {
        return (_a = document.querySelector("video > source")) === null || _a === void 0 ? void 0 : _a.getAttribute("src");
    });
}
function finishTask() {
    return __awaiter(this, void 0, void 0, function* () {
        const source = yield waitValue({
            predicate: getM3u8Source,
            waitInterval: 100,
        });
        try {
            const m3u8Response = yield fetch(source, {
                method: "get",
            });
            const m3u8Content = yield m3u8Response.text();
            let saveResponse = yield fetch("http://localhost:5678/finish", {
                method: "post",
                mode: "cors",
                body: JSON.stringify({
                    Link: document.location.href,
                    Content: m3u8Content,
                }),
            });
            if (!saveResponse.ok) {
                throw Error(saveResponse.statusText);
            }
        }
        catch (error) {
            console.log(error);
            return;
        }
    });
}
function getTask() {
    return __awaiter(this, void 0, void 0, function* () {
        while (true) {
            try {
                let taskResponse = yield fetch("http://localhost:5678/get", {
                    method: "get",
                    mode: "cors",
                });
                if (!taskResponse.ok) {
                    throw Error(taskResponse.statusText);
                }
                else {
                    const link = yield taskResponse.text();
                    if (link) {
                        document.location.replace(link);
                    }
                }
            }
            catch (error) {
                console.log("未获取到任务:" + error);
            }
            yield sleep(5000);
        }
    });
}
function main() {
    return __awaiter(this, void 0, void 0, function* () {
        let startBtn = document.createElement("button");
        startBtn.onclick = addTask;
        startBtn.innerText = "添加任务";
        startBtn.setAttribute("style", "position: fixed;top: 50%;left:0;");
        document.body.appendChild(startBtn);
        yield finishTask();
        getTask();
    });
}
main();