chinahrt全自动刷课

chinahrt自动刷课,只需将视频添加到播放列表,后续刷课由系统自动完成;基于https://github.com/yikuaibaiban/chinahrt修改。

// ==UserScript==
// @name         chinahrt全自动刷课
// @namespace    https://github.com/jsgang/chinahrt
// @version      1.1
// @description  chinahrt自动刷课,只需将视频添加到播放列表,后续刷课由系统自动完成;基于https://github.com/yikuaibaiban/chinahrt修改。
// @author       jsgang  yikuaibaiban  https://www.jsgang.top
// @icon         https://www.google.com/s2/favicons?sz=64&domain=jsgang.top
// @match        http://*.chinahrt.com/*
// @match        https://*.chinahrt.com/*
// @match        http://videoadmin.chinahrt.com.cn/videoPlay/play*
// @match        http://videoadmin.chinahrt.com/videoPlay/play*
// @match        https://videoadmin.chinahrt.com.cn/videoPlay/play*
// @match        https://videoadmin.chinahrt.com/videoPlay/play*
//
// @grant        unsafeWindow
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// @grant        GM_notification
//
// @license      GPL
// ==/UserScript==
/**
 * 课程预览页面
 * @type {number}
 */
const COURSE_PREVIEW = 0;
/**
 * 课程播放页面
 * @type {number}
 */
const COURSE_PALY = 1;
/**
 * 视频播放页面
 * @type {number}
 */
const VIDEO_PALY = 2;
/**
 * VUE课程预览页面
 * @type {number}
 */
const VUE_COURSE_PREVIEW = 3;
/**
 * 未知页面
 * @type {number}
 */
const UNKOWN_PAGE = 9999;
/**
 * 课程存储关键字
 * @type {string}
 */
const COURSES = "courses";
/**
 * 自动播放
 * @type {string}
 */
const AUTOPLAY = "autoPlay";
/**
 * 静音
 * @type {string}
 */
const MUTE = "mute";
/**
 * 拖动
 * @type {string}
 */
const DRAG = "drag";
/**
 * 播放速度
 * @type {string}
 */
const SPEED = "speed";
/**
 * 播放模式
 * @type {string}
 */
const PLAY_MODE = "play_mode";
/**
 * 重复次数
 * @type {string}
 */
const REAPT_NUM = "reapt_num";
/**
 * 自刷切换
 * @type {string}
 */
const REAPT_MODE = "reapt_mode";
/**
 * 获取自动播放
 * @returns {*}
 */
function getAutoPlay() {
    return GM_getValue(AUTOPLAY, true);
}

/**
 * 获取静音
 * @returns {*}
 */
function getMute() {
    return GM_getValue(MUTE, true);
}

/**
 * 获取拖动
 * @returns {*}
 */
function getDrag() {
    return GM_getValue(DRAG, 5);
}

/**
 * 获取播放速度
 * @returns {*}
 */
function getSpeed() {
    return GM_getValue(SPEED, 1);
}

/**
 * 获取播放列表
 * @returns {*|*[]}
 */
function getCourses() {
    var value = GM_getValue(COURSES, []);
    if (Array.isArray(value)) {
        return value;
    }
    return [];
}

/**
 * 添加到播放列表
 * @param element
 * @returns {boolean}
 */
function addCourse(element) {
    if (!element.title || !element.url) {
        console.error(element);
        alert("添加失败,缺少必要参数");
        return false;
    }

    var oldValue = getCourses();

    if (oldValue.findIndex(value => value.url == element.url) > -1) {
        alert("已经存在播放列表中");
        return false;
    }

    oldValue.push({title: element.title, url: element.url});

    GM_setValue(COURSES, oldValue);

    return true;
}

/**
 * 从播放列表移除
 * @param index
 */
function removeCourse(index) {
    var courses = getCourses();

    if (Number.isNaN(index)) {
        for (let i = courses.length; i >= 0; i--) {
            const element = courses[i];
            // 正则提取 href 中  sectionId courseId trainplanId
            var jsonHref = element.url;
            var jsonSectionId = jsonHref.match(/sectionId=([^&]*)/)[1];
            var jsonCourseId = jsonHref.match(/courseId=([^&]*)/)[1];
            var jsonTrainplanId = jsonHref.match(/trainplanId=([^&]*)/)[1];

            // 正则提取 window.location.href 中  sectionId courseId trainplanId
            var href = window.location.href;
            var sectionId = href.match(/sectionId=([^&]*)/)[1];
            var courseId = href.match(/courseId=([^&]*)/)[1];
            var trainplanId = href.match(/trainplanId=([^&]*)/)[1];

            if (jsonCourseId == courseId && jsonSectionId == sectionId && jsonTrainplanId == trainplanId) {
                courses.splice(i, 1);
            }
        }
    } else {
        courses.splice(index, 1);
    }

    GM_setValue(COURSES, courses);
}

/**
 * 生成可以添加到播放列表的容器
 * @returns {*|jQuery|HTMLElement}
 */
function createCanPlayList() {
    // 生成容器
    var playListBox = $("<div>", {
        id: "canPlayBox",
        css: {
            width: "300px",
            height: "500px",
            position: "fixed",
            top: "100px",
            background: "rgba(255,255,255,1)",
            right: "20px",
            border: "1px solid #c1c1c1"
        }
    });

    var status = $("<div></div>", {
        text: "获取中...",
        css: {
            height: "30px",
            "border-bottom": "1px solid",
            "text-align": "center",
            "line-height": "30px",
            "color": "#4bccf2",
            "font-weight": "bold"
        },
        click: function () {
            playListBox.trigger("clear");
            if (getPageNumber() == VUE_COURSE_PREVIEW) {
                vue_findCourses(playListBox);
            } else {
                findCourses(playListBox);
            }
        }
    });
    status.appendTo(playListBox);

    var listBox = $("<div></div>", {
        css: {
            height: "470px",
            "overflow-y": "auto"
        }
    }).appendTo(playListBox);

    playListBox.on("clear", function () {
        status.text("获取中...");
        listBox.empty();
    });

    // 添加绑定事件
    playListBox.on("bind", function (e, data) {
        if (status.text() == "获取中...") {
            status.text("点击刷新");
        }
        var box = $("<div>", {
            css: {
                "border-bottom": "1px solid #c1c1c1",
                "padding": "8px",
                "line-height": "150%",
                "border-bottom": "1px solid #c1c1c1",
                "margin-bottom": "3px"
            }
        });

        var ptitle = $("<p>", {
            text: data.title,
            title: data.title,
            css: {
                "font-size": "13px",
                "white-space": "nowrap",
                "overflow": "hidden",
                "text-overflow": "ellipsis",
            }
        });
        ptitle.appendTo(box);

        var pstatus = $("<p>", {
            text: "学习状态: " + data.status,
            title: "学习状态: " + data.status,
            css: {
                "font-size": "12px",
                "white-space": "nowrap",
                "overflow": "hidden",
                "text-overflow": "ellipsis",
                "color": "#c1c1c1"
            }
        });
        pstatus.appendTo(box);

        var disabled = getCourses().findIndex(value => value.url == data.url) > -1;
        var button = $("<button>", {
            text: disabled ? "已在列表中" : "添加到播放列表",
            type: "button",
            disabled: disabled,
            css: {
                color: disabled ? "#000" : "#FFF",
                backgroundColor: disabled ? "#c3c3c3" : "#4bccf2",
                border: "none",
                padding: "5px 10px",
                "margin-top": "4px"
            },
            click: function () {
                if (addCourse({title: data.title, url: data.url})) {
                    $(this).attr("disabled", true);
                    $(this).css({
                        color: "#000",
                        backgroundColor: "#c3c3c3",
                    }).text("已在列表中");
                }
            }
        });
        button.appendTo(box);

        box.appendTo(listBox);
    });

    playListBox.appendTo('body');

    return playListBox;
}

/**
 * 显示通知
 * @param content
 */
function showNotification(content) {
    GM_notification({
        text: content,
        title: "Chinahrt自动刷课",
        image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAArFJREFUWEftlttPE0EUxr+9ddtdYOXSSmmlFFoasSFemmg0qYkIMfGF/9J/wTeN0cSYGBHEBBIoLSIU0VrKpe1eagaySWVmutu+GJPO4+5cfvOdc745wkGl3sI/HEIf4L9ToHrqoHLi4LTRgmm1IAhAMCDgmi4ibEgQhe4SyncOFA9tFMoWaucO9wRJFDAZlpCeUKAq/kA8AY7PHKwWmqic+i8WRRaQTciIj8qeFB0Bjo4dvN9ooOX/7L8OnLshYybaWQouALn5m/XeD3dJ5qcCSEQkrhJcgLfrdabshV8mvtdsPEoEPeV1JzzOqhjSROZ8JsBO2cJa0WQueLFSQ6lqYWpYQT4ZQnSQfzt3g+iwhFw64B/g9VqDm+0uANlNkYB8UkMupnqqkc+qMBgqUAqQOiex5412AHdOJhzAUlqDpvBNIBOXMTtBJyQF0El+ciALgHwfUEUspjTMjrGzPmKIuJ+hlaIA1ksmtg+srhRon7wwE0IuTieoHhTwZJ7+TgGsbDexe2T3DJAdV/E8o1HriTMu3QlR3ymAz4UmSj96A1AkActzOqZH6DD4BtjYM7G5130IYkMynmV0jHHqfXRQxMObPnKg/NvGh81mVyG4HQ1gcVYH22out5oel3Fr0kcVOC3g5cdz2JxH72oVPE1ruDfh7QMPMirCBo3IdMIvRfPi6WUNF2BMl0Aynjii1yAGRIyINZgADRN4tVa/aDiujnfFOg5PbCykNAyp/roPYsPEjn0DkInfflr4tMV+D7xu3P4/eV1GNsFXqWM/sLVv4usuvyK8QGIjEu6m2I+Qu9azIyKt2OoOvyp4EF439w1AJpLmhHjDfoVvUO6GJOHSMZkb86vAngq0L6ieOSA+UalddsWWfZmkA0ERhi4iYkjMUusUqq4AvGLey/8+QF+BP0npcPDdfTv7AAAAAElFTkSuQmCC",
    });
}

/**
 * 创建配置窗口
 */
function createConfigBox() {
    var box = $("<div>", {
        css: {
            position: "fixed",
            right: 0,
            top: 0,
            width: "250px",
            height: "240px",
            "background-color": "#FFF",
            "z-index": 9999,
            border: "1px solid #ccc"
        }
    });

    $("<div>", {
        text: "视频控制配置",
        css: {
            "border-bottom": "1px solid #ccc",
            padding: "5px",
            "font-weight": "bold"
        }
    }).appendTo(box);

    var configBox = $("<div>", {
        css: {
            padding: "5px",
            "padding-bottom": "5px",
            "font-size": "12px",
            "line-height": "150%"
        }
    });

    // 自动播放
    var autoPlayBox = $("<div>", {css: {"border-bottom": "1px dotted #ccc", "padding-bottom": "5px"}});
    $("<p>", {text: "是否自动播放:"}).appendTo(autoPlayBox);
    $("<input>", {
        type: "radio", name: "autoPlay", value: true, checked: getAutoPlay(), click: function () {
            GM_setValue(AUTOPLAY, true);
        }
    }).appendTo(autoPlayBox);
    $("<label>", {text: "是"}).appendTo(autoPlayBox);
    $("<input>", {
        type: "radio", name: "autoPlay", value: false, checked: !getAutoPlay(), click: function () {
            GM_setValue(AUTOPLAY, false);
        }
    }).appendTo(autoPlayBox);
    $("<label>", {text: "否"}).appendTo(autoPlayBox);
    autoPlayBox.appendTo(configBox);

    // 是否静音
    var mutePlayBox = $("<div>", {css: {"border-bottom": "1px dotted #ccc", "padding-bottom": "5px"}});
    $("<p>", {text: "是否静音:"}).appendTo(mutePlayBox);
    $("<input>", {
        type: "radio", name: "mute", value: true, checked: getMute(), click: function () {
            GM_setValue(MUTE, true);
        }
    }).appendTo(mutePlayBox);
    $("<label>", {text: "是"}).appendTo(mutePlayBox);
    $("<input>", {
        type: "radio", name: "mute", value: false, checked: !getMute(), click: function () {
            GM_setValue(MUTE, false);
        }
    }).appendTo(mutePlayBox);
    $("<label>", {text: "否"}).appendTo(mutePlayBox);
    $("<p>", {
        text: "注意:不静音,视频可能会出现不会自动播放",
        css: {"font-size": "13px", "font-weight": "bold"}
    }).appendTo(mutePlayBox);
    mutePlayBox.appendTo(configBox);

    // 启用拖放
    var dragPlayBox = $("<div>", {css: {"border-bottom": "1px dotted #ccc", "padding-bottom": "5px"}});
    $("<p>", {text: "启用拖放(慎用):"}).appendTo(dragPlayBox);
    $("<input>", {
        type: "radio", name: "drag", value: 5, checked: getDrag() == 5, click: function () {
            GM_setValue(DRAG, 5);
        }
    }).appendTo(dragPlayBox);
    $("<label>", {text: "还原"}).appendTo(dragPlayBox);
    $("<input>", {
        type: "radio", name: "drag", value: 1, checked: getDrag() == 1, click: function () {
            GM_setValue(DRAG, 1);
        }
    }).appendTo(dragPlayBox);
    $("<label>", {text: "启用"}).appendTo(dragPlayBox);
    dragPlayBox.appendTo(configBox);
 var playModeBox = $("<div>", {css: {"border-bottom": "1px dotted #ccc", "padding-bottom": "5px"}});

    playModeBox.appendTo(configBox);

    configBox.appendTo(box);

    box.appendTo("body");
}

/**
 * 创建播放列表窗口
 */
function createPlayListBox() {
    var box = $("<div>", {
        id: "playListBox",
        css: {
            position: "fixed",
            right: 0,
            top: 250,
            width: "250px",
            height: "450px",
            "background-color": "#FFF",
            "z-index": 9999,
            border: "1px solid #ccc",
            "overflow-y": "auto"
        }
    });

    $("<div>", {
        text: "视频列表",
        css: {
            "border-bottom": "1px solid #ccc",
            padding: "5px",
            "font-weight": "bold"
        }
    }).appendTo(box);

    // 渲染课程列表
    var courses = getCourses();
    for (let index = 0; index < courses.length; index++) {
        const element = courses[index];

        var ptitle = $("<p>", {
            text: element.title,
            title: element.title,
            css: {
                "font-size": "13px",
                "white-space": "nowrap",
                "overflow": "hidden",
                "text-overflow": "ellipsis",
            }
        });
        ptitle.appendTo(box);

        var button = $("<button>", {
            text: "移除",
            type: "button",
            data: {index: index},
            css: {
                color: "#FFF",
                backgroundColor: "#fd1952",
                border: "none",
                padding: "5px 10px",
                "margin": "4px 0 10px 0",
            },
            click: function () {
                if (confirm("确定删除这个视频么?")) {
                    removeCourse($(this).data("index"));
                }
            }
        });
        button.appendTo(box);
    }

    box.appendTo("body");
}

/**
 * 获取当前页面编号
 * @returns {number}
 */
function getPageNumber() {
    var href = window.location.href;
    // 以下是Vue版的请求地址
    if (href.indexOf("/index.html#/v_courseDetails") > -1) {
        return VUE_COURSE_PREVIEW;
    }
    // 默认课程详情地址
    if (href.indexOf("/course/preview") > -1) {
        return COURSE_PREVIEW;
    }
    if (href.indexOf("/course/play_video") > -1) {
        return COURSE_PALY;
    }
    if (href.indexOf("/videoPlay/play") > -1) {
        return VIDEO_PALY;
    }

    return UNKOWN_PAGE;
}

/**
 * 获取课程信息
 * @param playListBox
 */
function findCourses(playListBox) {
    // 提取所有链接
    var allLinks = document.querySelectorAll("a");
    // 提取所有可以播放的数据
    for (let i = 0; i < allLinks.length; i++) {
        const element = allLinks[i];
        if (element.href.indexOf("/course/play_video") > -1) {
            playListBox.trigger("bind", {
                title: element.innerText,
                url: element.href,
                status: $(element).prev().text()
            });
        }
    }
}

/**
 * VUE版本获取课程信息
 * @param playListBox
 */
function vue_findCourses(playListBox) {
    // 获取data
    var data = document.querySelector("article")?.__vue__?._data;
    if (!data) {
        return;
    }

    // 获取页面信息
    var pageData = data?.pageData;
    if (!pageData) {
        return;
    }

    // 获取所有章节信息
    var chapters = pageData?.course?.chapter_list;

    // 循环获取章节信息
    if (chapters && chapters.length > 0) {
        for (let i = 0; i < chapters.length; i++) {
            const chapter = chapters[i];
            // 循环分段(课时)
            var sections = chapter?.section_list;
            if (sections && sections.length > 0) {
                for (let j = 0; j < sections.length; j++) {
                    const section = sections[j];
                    // 拼接课时网址
                    var url = window.location.protocol + "//" + window.location.host + window.location.pathname + "#/v_video?platformId=" + data.platformId + "&trainplanId=" + data.trainplanId + "&courseId=" + data.courseId + "&sectionId=" + section.id;
                    playListBox.trigger("bind", {
                        title: section.name,
                        url: url,
                        status: section.study_status + "( " + section.studyTimeHHmmss + " )"
                    });
                }
            }
        }
    }
}

window.onload = function () {
    try {
        // 检测到是Vue
        if (Vue) {
            console.log("当前是Vue模式");
            // 创建播放列表
            var playListBox;
            // 循环检测
            setInterval(() => {
                if (getPageNumber() == VUE_COURSE_PREVIEW) {
                    if (!playListBox) {
                        playListBox = createCanPlayList();
                        setTimeout(function () {
                            vue_findCourses(playListBox);
                        }, 1000);
                    }
                } else {
                    if (playListBox) {
                        playListBox.remove();
                        playListBox = undefined;
                    }
                }
            }, 1000);
        }
    } catch (error) {
        console.log("当前不是Vue模式");
    }


    if (getPageNumber() == COURSE_PREVIEW) {
        $(document).ready(function () {
            // 创建播放列表
            var playListBox = createCanPlayList();
            findCourses(playListBox);
        });
    }

    if (getPageNumber() == VIDEO_PALY) {
        $(document).ready(function () {

            // 增加提示信息
            $('<div></div>', {
                html: "点击课程详情页中的插件提供的【添加到播放列表】按钮添加需要自动播放的课程。受到浏览器策略影响第一次可能无法自动播放,请手动点击播放。",
                css: {
                    "font-size": "14px",
                    "font-weight": "bold",
                    color: "red",
                    background: "#FFF",
                    position: "absolute",
                    "line-height": "30px",
                    "z-index": "99999",
                    "left": "30px",
                    bottom: "10px"
                }
            }).prependTo("#body");

            $("video").prop("muted", "muted");

            // 移除讨厌的事件
            removePauseBlur();

            // 视频播放初始化
            function run() {
                 // 总是显示播放进度
                player.changeControlBarShow(true);

                // 拖动开关
                player.changeConfig('config', 'timeScheduleAdjust', getDrag());

                // 静音
                if (getMute()) {
                    player.videoMute();
                } else {
                    +
                        player.videoEscMute();
                }

                // 播放速度
                player.changePlaybackRate(getSpeed());

                // 自动播放
                if (getAutoPlay()) {
                    player.videoPlay();
                }
            }

            // 视频总长度
            var videoDuration = 0;
            var startstaus=0;
            var actisok=0;
            var ctimes=0;
            var rtimes=0;
             var rtimess=0;
            var jumpas=0;
            var nonum=0;

             var tmp = setInterval(function () {
                if (player != undefined) {
                    player.addListener('loadedmetadata', run);
                    run();
                    clearInterval(tmp);


                    // 移除本课程学习完毕
                    attrset.proxyUrl = "";

                    // 播放结束
                    player.addListener('ended', function () {
                        removeCourse(window.location.href);
                        var courses = getCourses();
                        if (courses.length == 0) {
                            GM_setValue(REAPT_MODE, 0);
                            GM_setValue(REAPT_NUM, 0);
                            showNotification("所有视频已经播放完毕");
                        } else {
                            GM_setValue(REAPT_MODE, 0);
                            GM_setValue(REAPT_NUM, 0);
                           
                            showNotification("即将播放下一个视频:" + courses[0].title);
                            window.top.location.href = courses[0].url;
                           
                        }
                    });


                    player.addListener('time', function (t) {
                        videoDuration = parseInt(player.getMetaDate().duration);
                      var tmpurl=$(location).attr("href");

                        if(tmpurl.indexOf("ifDrag=0")==-1){

                            if(ctimes==0){
                                player.videoSeek(videoDuration-4);
                                ctimes=1;
                            }


                        }else{
                            tmpurl=tmpurl.replace("ifPauseAd=1&ifPauseBlur=1","ifPauseAd=0&ifPauseBlur=0");
                            tmpurl=tmpurl.replace("ifDrag=0","ifDrag=1");
                        if(attrset.currentTime>3){
      self.location.href=tmpurl;

                        }
                        }

                    });
                }
            }, 1000);

            // 创建配置窗口
            createConfigBox();

            // 创建播放列表窗口
            createPlayListBox();



            // 检测播放列表
            GM_addValueChangeListener(COURSES, function (name, oldValue, newValue, remote) {
                console.log("检测播放列表变动");
                $("#playListBox").remove();
                createPlayListBox();
            });

            // 监测自动播放
            GM_addValueChangeListener(AUTOPLAY, function (name, oldValue, newValue, remote) {
                console.log("监测自动播放变动");
                if (newValue) {
                    player.videoPlay();
                }
            });

            // 检测静音
            GM_addValueChangeListener(MUTE, function (name, oldValue, newValue, remote) {
                console.log("检测静音变动");
                if (newValue) {
                    player.videoMute();
                } else {
                    player.videoEscMute();
                }
            });

            // 检测拖动
            GM_addValueChangeListener(DRAG, function (name, oldValue, newValue, remote) {
                console.log("检测拖动变动");
                player.changeConfig('config', 'timeScheduleAdjust', newValue);
            });

            // 检测速度
            GM_addValueChangeListener(SPEED, function (name, oldValue, newValue, remote) {
                console.log("检测速度变动");
                player.changePlaybackRate(newValue);
            });
        });
    }
}