Fuck Chaoxing

解除超星自动暂停播放的限制并添加自动播放下一集的功能

目前為 2018-06-06 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name			Fuck Chaoxing
// @namespace		[email protected]
// @description		解除超星自动暂停播放的限制并添加自动播放下一集的功能
// @author			依然独特
// @version			1.1.1
// @grant			none
// @run-at			document-start
// @require			https://greasyfork.org/scripts/18715-hooks/code/Hooks.js?version=126794
// @require			https://greasyfork.org/scripts/29782-docsready/code/docsReady.js?version=195016
// @include			*://*.chaoxing.com/knowledge/cards*
// @include			*://*.chaoxing.com/ananas/modules/video/index.html*
// @include			*://*.chaoxing.com/ananas/modules/work/index.html
// @include			*://*.chaoxing.com/ananas/modules/work/index.html*
// @match			*://*.chaoxing.com/knowledge/cards*
// @match			*://*.chaoxing.com/ananas/modules/video/index.html*
// @match			*://*.chaoxing.com/ananas/modules/work/index.html
// @match			*://*.chaoxing.com/ananas/modules/work/index.html*
// @license			BSD 2-Clause
// @homepageURL		https://gist.github.com/xymopen/eb65046644ff5cb7c0668e5d4f9607d1
// ==/UserScript==

( function () {
	"use strict";

	function hookJQuery( onPlayerInit, contextWindow ) {
		if ( !contextWindow ) {
			contextWindow = window;
		}

		// CXPlayer extends jQuery for its own APIs
		// so hook jQuery to modify these APIs.
		Hooks.set( contextWindow, "jQuery", function ( target, propertyName, ignored, jQuery ) {
			Hooks.set( jQuery.fn, "cxplayer", function ( target, propertyName, oldValue, newValue ) {
				return Hooks.apply( newValue, function ( target, thisArg, args ) {
					var config = args[ 0 ], $player;

					config.datas.pauseAdvertList = [];
					config.datas.preAdvertList = [];
					config.datas.isAutoPlayNext = true;
					config.datas.isDefaultPlay = true;

					if ( config.events &&
						config.events.onAnswerRight &&
						!config.events.onAnswerRight.toString()
							.replace( /(function .*?\(.*?\))/g, "" ).trim()		// remove function signifigure
							.replace( /^\{|\}$/g, "" )
							.replace( /\/\/.*(\r|\n|(\r\n))/g, "" )				// remove single line comment
							.replace( /\/\*.*\*\//mg, "" )						// remove multiple line comment
							.match( /^\s*$/ )
					) {
						contextWindow.alert( "onAnswerRight() is not empty. It's unsafe to block the resource URL." );
					}

					$player = Hooks.Reply.apply( arguments );

					$player.switchWindow = function () {
						/* empty */
						console.debug( "[Fuck Chaoxing]moocPlayer.switchWindow() is invoked." );
					};

					$player.bind( "onPause", function () {
						$player.playMovie();
					} );

					onPlayerInit( $player, config );

					return $player;
				} );
			} );

			Hooks.set( jQuery.fn, "pauseMovie", function ( target, methodName, oldValue, newValue ) {
				return function () {
					/* empty */
				};
			} );

			return Hooks.Reply.set( arguments );
		} );
	};

	function next( contextDocument ) {
		var selections, nextSelectionIndex;

		function findCurIdx( nodeList ) {
			return Array.from( nodeList ).findIndex( function ( chapter ) {
				return chapter.classList.contains( "currents" );
			} );
		};

		contextDocument = contextDocument || document;

		selections = contextDocument.querySelectorAll( "#mainid .tabtags span" );
		nextSelectionIndex = findCurIdx( selections ) + 1;

		if ( nextSelectionIndex < selections.length ) {
			selections[ nextSelectionIndex ].click();
		} else {
			( function clickNextChapter() {
				var chapters = contextDocument.querySelectorAll(
					"#coursetree .ncells h1," +
					"#coursetree .ncells h2," +
					"#coursetree .ncells h3," +
					"#coursetree .ncells h4," +
					"#coursetree .ncells h5," +
					"#coursetree .ncells h6"
				),
					curChapterIndex = findCurIdx( chapters ),
					nextChapterIndex = curChapterIndex + 1,
					nextChapter = chapters[ nextChapterIndex ],
					lastestChapterIndex = Array.prototype.findIndex.call( chapters, chapter => chapter.querySelector( ".orange01" ) ),
					lastestChapter = chapters[ lastestChapterIndex ];

				// Upon first entry there may already be a few chapters finished
				// Directly jump to the lastest chapter
				if ( lastestChapterIndex > curChapterIndex &&
					!lastestChapter.querySelector( ".lock" ) ) {
					lastestChapter.click();
				} else if ( nextChapterIndex < chapters.length ) {
					// Wait some time for the next chapter to unlock
					if ( nextChapter.querySelector( ".lock" ) ) {
						setTimeout( clickNextChapter, 1e3 );
					} else {
						nextChapter.click();
					}
				}
			} )();
		}
	};

	function tryNext( contextDocument ) {
		// Check if we have finished current selection
		if ( window.parent.document.querySelector( ".ans-job-finished" ) ) {
			// Automatically switch to next chapter
			next( window.top.document );
		}
	};

	if ( ( /\/ananas\/modules\/video\/index.html/ ).test( window.location.pathname ) ) {
		hookJQuery( function ( $player, config ) {
			$player.bind( "onInitComplete", tryNext );

			// Automatically switch to next selection
			$player.bind( "onEnd", function ( event, index, config ) {
				// Only execute once
				var executed = false;

				// Wait for the player to log your trace by triggering logFunc event
				window.jQuery( document ).ajaxComplete( function () {
					if ( !executed ) {
						executed = true;
						tryNext();
					}
				} );
			} );
            
            $player.bind( "onError", function() {
				let state = [ "error", "playing", "paused", "hanging", "stop" ][ $player.getPlayState() ];
                
                if ( 4 === $player.getPlayState() ) {
                    window.location.reload();
                }
			} );

            /*
			[ "onInit", "onInitComplete", "onNotVideoUrl", "onGoPlay", "onShare", "onUnlock", "onTurnOff", "onPointStart", "onPointEnd", "onChangeLine", "onEnd", "onStart", "onDownload", "onPlayProgress", "onSendProgressSuccess", "onSendProgressError", "onError", "onRightIconClick", "onMovieDrag", "onPlay", "onPause", "onAnswerWrong", "onAnswerRight", "sendlogzt", "logFunc" ]
				.forEach( e => $player.bind( e, () => {
					let state = [ "error", "playing", "paused", "hanging", "stop" ][ $player.getPlayState() ];

					console.debug( `[Fuck Chaoxing]${ e } is triggered. Player is ${ state }.` );
				} ) );
                */
		} );
	} else if ( ( /\/ananas\/modules\/work\/index.html/ ).test( window.location.pathname ) ) {
		domReady( function () {
			frameReady( tryNext, document.querySelector( "#frame_content" ) );
		} );
	} else if ( ( /\/knowledge\/cards/ ).test( window.location.pathname ) ) {
		// parent frame of /ananas/modules/video/index.html or /ananas/modules/work/index.html
		// there are some pages where there is no such content frame
		domReady( function () {
			if ( !document.querySelector( "iframe" ) ) {
				next( window.top.document );
			}
		} );
	}
} )();