Greasy Fork

Greasy Fork is available in English.

基金业协会视频自动播放

基金业协会视频自动下一个,但题目目前需要自己答。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         基金业协会视频自动播放
// @namespace    https://www.nekotofu.top/
// @homepage    https://www.nekotofu.top/
// @version      1.3.1
// @description 基金业协会视频自动下一个,但题目目前需要自己答。
// @author       misaka10032w
// @match        *://peixun.amac.org.cn/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @noframes
// @license MIT
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function () {
    'use strict';
    // 检查浏览器是否支持通知并在页面加载时请求权限
    if (!("Notification" in window)) {
        console.log("浏览器不支持通知");
    } else if (Notification.permission !== "granted") {
        Notification.requestPermission().then(permission => {
            if (permission !== "granted") {
                customLog("用户拒绝了通知权限", "red");
            }
        });
    }
    function sendNotification(title, content) {
        if (Notification.permission === "granted") {
            showNotification(title, content);
        } else {
            customLog("通知权限未授予,需要点击地址栏左边按钮重置通知权限", "red");
        }
    }
    function showNotification(title, content) {
        const notification = new Notification(title, { body: content });
        notification.onclick = () => {
            // TODO
            customLog("用户点击了通知", "green");
        };
    }
    //自定义LOG
    function customLog(message, backgroundColor, color = "white") {
        console.log(`%c${message}`, `background: ${backgroundColor}; color: ${color}; padding: 2px 4px; border-radius: 2px;`);
    }
    //关闭弹窗,这个方法不好使了,暂时不想改了,不耽误播放
    function closePopup() {
        const pop = document.querySelector(".class_float");
        if (pop.style.display != "none") {
            var close = pop.getElementsByClassName("btn-close")[0]
            close.click();
        }
    }
    //获取课程列表
    let nowPlaying;
    function getCourse() {
        const courseList = document.querySelectorAll(".catalog-content a");
        const ignoredClasses = ["studied", "test", "testRev", "testScore"];
        for (const course of courseList) {
            const hasIgnoredClass = ignoredClasses.some(cls => course.classList.contains(cls));
            if (!hasIgnoredClass) {
                customLog("存在未播放的项,播放列表未完成:", "yellow", "black");
                nowPlaying = course;
                customLog(nowPlaying.textContent, "yellow", "black");
                if (!nowPlaying.classList.contains("cur")) {
                    customLog("已播放完毕", "green");
                    nowPlaying.click();
                }
                return nowPlaying;
            }
        }
        // 所有项都已经播放,播放列表已完成
        return false;
    }
    //注册菜单
    const defaultPlaybackRate = 1.0;
    let playBackRate = GM_getValue('playBackRate', defaultPlaybackRate);
    const defaultMute = true;
    let playbackRateMenu = GM_registerMenuCommand(`播放速率:${GM_getValue('playBackRate', defaultPlaybackRate)}`, setPlaybackRate);
    let muteMenu = GM_registerMenuCommand(`${GM_getValue('isMute', defaultMute) ? '🔇' : '🔊'} 是否静音播放`, toggleMute);
    function setPlaybackRate() {
        const newRate = prompt('请输入新的播放速率,不建议太高,可能会被检测:', playBackRate);
        if (newRate !== null) {
            playBackRate = parseFloat(newRate);
            GM_setValue('playBackRate', playBackRate);
            updateMenuCommands();
        }
    }
    function toggleMute() {
        let isSetMute = GM_getValue('isMute', defaultMute);
        GM_setValue('isMute', !isSetMute);
        updateMenuCommands();
    }
    function updateMenuCommands() {
        GM_unregisterMenuCommand(playbackRateMenu);
        GM_unregisterMenuCommand(muteMenu);
        playbackRateMenu = GM_registerMenuCommand(`播放速率:${GM_getValue('playBackRate', defaultPlaybackRate)}`, setPlaybackRate);
        muteMenu = GM_registerMenuCommand(`${GM_getValue('isMute', defaultMute) ? '🔇' : '🔊'} 是否静音播放`, toggleMute);
    }
    //注册播放器事件
    function setupVideoPlayerEvents(player) {
        player.addEventListener("play", function () {
            customLog("视频开始播放", "green");
        });
        player.addEventListener("pause", function () {
            customLog("视频暂停,将在1000ms后继续播放", "red");
            setTimeout(() => { player.play(); }, 1000);
        });
        player.addEventListener("ended", function () {
            customLog("视频播放结束", "green");
        });
        player.addEventListener("timeupdate", function () {
            const currentplaybackRate = player.playbackRate;
            const isSetMute = GM_getValue('isMute', defaultMute);
            if (player.muted != isSetMute) {
                player.muted = isSetMute;
            }
            if (currentplaybackRate != playBackRate) {
                player.playbackRate = playBackRate;
            }
        })
    }
    function monitorPlayback(player) {
        let maxTime = 0;
        setInterval(() => {
            const currentTime = player.currentTime.toFixed(0);
            const duration = player.duration.toFixed(0);
            //console.log(`当前时间: ${currentTime} / 总时长: ${duration}`);
            //如果当前播放等于时长并且nowPlaying不为false(为文本代表有课程未看)则重新加载,防止更新延迟导致重看
            if (currentTime == duration && nowPlaying) {
                setTimeout(() => {
                    location.reload();
                }, 1000);
            } else if (currentTime != currentTime && player.paused) {
                player.play();
            }
            //记录一下当前时间,如果最新时间突然变小,证明视频被重新播放了
            customLog(`记录的时间:${maxTime}\n现在的时间:${currentTime}`, "green");
            maxTime = Number(currentTime) >= maxTime ? Number(currentTime) : (location.reload(), maxTime);
        }, 1000);
    }
    //播放处理
    if (document.querySelectorAll(".catalog-content a").length != 0) {
        nowPlaying = getCourse();
        //检查是否播放完毕,class包含studied即播放完毕
        if (!nowPlaying) {
            sendNotification("当前课程播放完毕!", "当前课程列表播放完毕,请考试或者切换下一个课程!")
            return true
        }
        //检查iframe,网站的播放器是个iframe,什么鬼写法
        var iframe = document.querySelector('iframe');
        let checkInterval = setInterval(function () {
            iframe = document.querySelector('iframe');
            if (iframe) {
                let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
                let player = iframeDocument.getElementsByTagName("video")[0];
                console.log('找到播放器!:', player);
                setupVideoPlayerEvents(player);
                monitorPlayback(player)
                player.muted = true;
                player.play();
                clearInterval(checkInterval);
            }
        }, 500);
    }
})();