Greasy Fork

来自缓存

Greasy Fork is available in English.

学起Plus挂课自动连续播放

一个网课挂机自动连续播放工具,仅适用于学起Plus sccchina.net chinaedu.net,反馈与交流QQ群:715307684

当前为 2022-10-25 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         学起Plus挂课自动连续播放
// @namespace    http://tampermonkey.net/
// @version      0.121
// @description  一个网课挂机自动连续播放工具,仅适用于学起Plus sccchina.net chinaedu.net,反馈与交流QQ群:715307684
// @author       哆哆啦啦梦
// @match        *://*.sccchina.net/*
// @match        *://rspcourse.chinaedu.net/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chinaedu.net
// @grant        none
// @license      GPLv3
// ==/UserScript==

const timeInterval = 5 * 1000;
let lessionInfo = {};
let videoModuleInfo = {};
let lessionResAll = [];
let currRes = undefined;
let courseEnd = false;
let nextRes = null;

function getLessionRes(arr) {
  arr.forEach((e) => {
    if (e.res) {
      for (let item of e.res) {
        item.name = e.name + ' - ' + item.name;
        // 添加到数组
        lessionResAll.push(item);
      }
    }

    if (e.child) {
      getLessionRes(e.child);
    }
  });
}

function checkCoursePage() {
  if (lessionResAll && lessionResAll.length) {
    // 取出第一个
    const firstRes = lessionResAll[0];
    // 查询是否元素存在
    if (document.querySelector(`li[nid='${firstRes.id}']`) === null) {
      // 不存在,代表非视频页
      // 获取当前选中的模块
      const active = document.querySelector("li.fl.cur");

      if (!active || active.getAttribute("nid") !== videoModuleInfo.id) {
        console.log(
          `当前课程模块不是视频模块!即将转到视频模块,ID:${videoModuleInfo.id}`
        );

        // 查找视频模块标签并点击
        document.querySelector(`li[nid='${videoModuleInfo.id}']`).click();
      }
    }
  }
}

function getNext() {
  // 获取当前res在全部res中的索引并加1指向下一个
  const index = lessionResAll.findIndex((e) => e.id === currRes.id) + 1;

  if (index < lessionResAll.length) {
    // 下一个res
    const nextRes = lessionResAll[index];

    console.log("即将播放下一个RES:", nextRes);

    // 生成新的src
    let nextSrc = undefined;

    if (nextRes.type === "video") {
      nextSrc = `com/video.html?url=${nextRes.url}&pos=0&cid=${nextRes.id}`;
    } else if (nextRes.type === "sfp") {
      nextSrc = `com/video.html?url=${nextRes.url}&pos=null&msg=null`;
    } else {
      console.log("未知RES类型:", nextRes);
    }

    return nextSrc;
  }

  return undefined;
}

function updateCurrRes() {
  // 获取课程内容容器
  const courseCon = document.querySelector(".courseCon iframe");

  if (courseCon === null) {
    // 检查是否课程页面
    return checkCoursePage();
  }

  // 获取加载的地址
  const iframeSrc = courseCon.getAttribute("src");

  // 根据src获取对应课程res信息
  // lessionResAll -> 元素 -> url 中的空格会被编码,所以需要 decodeURI
  const getRes = lessionResAll.find(
    (e) => decodeURI(iframeSrc).indexOf(decodeURI(e.url)) >= 0
  );

  // 检查是否匹配到视频res
  if (getRes === undefined) {
    // 检查是否课程页面
    return checkCoursePage();
  }

  if (currRes === undefined || currRes.id !== getRes.id) {
    // 设置currRes
    currRes = getRes;

    console.log("当前加载的课程URL:", iframeSrc);

    console.log("当前课程的RES:", currRes);

    // 查找导航条
    const breadcrumb = document.querySelector(".page-breadcrumb");
    // 设置标题
    breadcrumb &&
      (breadcrumb.innerHTML = `<b>当前正在播放:${currRes.name}</b>`);

    // 设置内容类型
    sessionStorage.setItem("contentType", currRes.type);
  }
}

function gotoNext() {
  // 获取视频状态
  const status = sessionStorage.getItem("play");

  if (status !== null && !courseEnd) {
    // 判断是否为end
    if (sessionStorage.getItem("play") === "end") {
      // 获取下一个地址
      const nextUrl = getNext();

      if (nextUrl) {
        // 获取课程内容容器
        const courseCon = document.querySelector(".courseCon iframe");

        // 设置新的src
        courseCon.setAttribute("src", nextUrl);
      } else {
        if (!courseEnd) {
          courseEnd = true;
          alert("播放结束,不存在下一个播放视频");
          console.log("播放结束,不存在下一个播放视频");
        }
      }
    }

    // 移除掉,避免再次错误判断
    sessionStorage.removeItem("play");
  }
}

function findLession() {
  // 延迟执行
  setTimeout(() => {
    // 处理弹窗
    const pop = document.querySelector("#pop");

    // 存在就点击关闭按钮
    pop && pop.querySelector(".pop_close").click();

    // 处理课程信息
    if (!courseInfo) {
      return alert("获取当前课程信息失败!");
    }

    // 提取课程信息
    lessionInfo = {
      id: courseInfo.id,
      name: courseInfo.name,
    };

    console.log(`当前课程:${lessionInfo.name},ID:${lessionInfo.id}`);

    // 提取课程模块
    const module = courseInfo.child.$model;

    console.log("模块信息:", module);

    // 查找视频模块索引
    const index = module.findIndex(
      (e) => e.name === "视频学习" || (e.code && e.code === "course")
    );

    // 提取视频模块信息
    videoModuleInfo = {
      id: module[index].id,
      name: module[index].name,
    };

    console.log("视频模块信息:", videoModuleInfo);

    // 提取课程Res
    getLessionRes(module[index].child);

    console.log("课程Res信息:", lessionResAll);
  }, timeInterval);

  // 定时执行
  setInterval(() => {
    // 更新currRes
    updateCurrRes();

    // 符合条件跳到下一个
    gotoNext();
  }, timeInterval);
}

function checkWorkTime() {
  // 不检查时间
  return true;
  const hour = new Date().getHours();
  if (hour < 9 || hour > 22) {
    return false;
  } else {
    return true;
  }
}

function courseLearn() {
  const getVideoProgress = () => {
    // 获取视频元素
    const video = document.querySelector("video");

    if (!checkWorkTime()) {
      const hour = new Date().getHours();
      const mins = new Date().getMinutes();
      // 非工作时间
      console.log("非工作时间:", hour, mins);
      // 暂停 情况下 播放视频
      !video.paused && video.pause();
      return;
    }

    // 设置静音
    video.muted = true;

    // 获取当前播放进度和视频长度 保留一位小数
    const currentTime = video.currentTime.toFixed(1);
    const totalTime = video.duration.toFixed(1);

    console.log(`当前进度:${currentTime}/${totalTime}`);

    if (currentTime < totalTime - 5) {
      // 视频没有播放完
      if (video.paused) {
        console.log("视频被暂停,继续播放!");
        video.play();
      } else {
        // 设置视频状态 播放
        sessionStorage.setItem("play", "start");
      }
    } else {
      // 视频播放完毕
      console.log("视频播放完毕!");
      // 设置标记 播放完毕
      sessionStorage.setItem("play", "end");
    }
  };

  // 定时执行
  setInterval(() => {
    // 获取内容类型
    const type = sessionStorage.getItem("contentType");

    if (type !== null) {
      if (type === "video") {
        getVideoProgress();
      } else if (type === "sfp") {
        // 设置标记 播放完毕
        sessionStorage.setItem("play", "end");
      } else {
        console.log("未知内容类型:", type);
      }
    }
  }, timeInterval);
}

(function () {
  "use strict";

  const url = document.URL;

  if (url.indexOf("//rspcourse.chinaedu.net/") !== -1) {
    if (url.indexOf("/play.html") >= 0) {
      // 课件页面,查找课程
      findLession();
    } else {
      // 课程学习
      courseLearn();
    }
  } else {
    console.log("未知页面");
  }
})();