改善优#官方html5播放器播放体验
'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // ==UserScript== // @name ykh5p // @namespace https://github.com/gooyie/ykh5p // @homepageURL https://github.com/gooyie/ykh5p // @supportURL https://github.com/gooyie/ykh5p/issues // @version 0.12.5 // @description 改善优#官方html5播放器播放体验 // @author gooyie // @license MIT License // // @include *://v.youku.com/* // @include *://player.youku.com/embed/* // @grant GM_info // @grant GM_addStyle // @grant unsafeWindow // @run-at document-start // ==/UserScript== (function () { 'use strict'; /* eslint-disable no-console */ var Logger = function () { function Logger() { _classCallCheck(this, Logger); } _createClass(Logger, null, [{ key: 'log', value: function log() { var _console; for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } (_console = console).log.apply(_console, ['%c' + this.tag + '%c' + args.shift(), 'color: #fff; background: #2FB3FF', ''].concat(args)); } }, { key: 'info', value: function info() { var _console2; for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } (_console2 = console).info.apply(_console2, [this.tag + args.shift()].concat(args)); } }, { key: 'debug', value: function debug() { var _console3; for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } (_console3 = console).debug.apply(_console3, [this.tag + args.shift()].concat(args)); } }, { key: 'warn', value: function warn() { var _console4; for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } (_console4 = console).warn.apply(_console4, [this.tag + args.shift()].concat(args)); } }, { key: 'error', value: function error() { var _console5; for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } (_console5 = console).error.apply(_console5, [this.tag + args.shift()].concat(args)); } }, { key: 'tag', get: function get() { return '[' + GM_info.script.name + ']'; } }]); return Logger; }(); /* eslint-enable no-console */ var Hooker = function () { function Hooker() { _classCallCheck(this, Hooker); } _createClass(Hooker, null, [{ key: '_hookCall', value: function _hookCall(cb) { var call = Function.prototype.call; Function.prototype.call = function () { for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { args[_key6] = arguments[_key6]; } var ret = call.apply(this, args); try { if (args && cb(args)) { Function.prototype.call = call; cb = function cb() {}; Logger.log('restored call'); } } catch (err) { Logger.error(err.stack); } return ret; }; this._hookCall = null; } }, { key: '_isEsModule', value: function _isEsModule(obj) { return obj.__esModule; } }, { key: '_isFuction', value: function _isFuction(arg) { return 'function' === typeof arg; } }, { key: '_isModuleCall', value: function _isModuleCall(args) { // module.exports, module, module.exports, require return args.length === 4 && args[1] && Object.getPrototypeOf(args[1]) === Object.prototype && args[1].hasOwnProperty('exports'); } }, { key: '_hookModuleCall', value: function _hookModuleCall(cb, pred) { var _this = this; var callbacksMap = new Map([[pred, [cb]]]); this._hookCall(function (args) { if (!_this._isModuleCall(args)) return; var exports = args[1].exports; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = callbacksMap[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = _slicedToArray(_step.value, 2), _pred = _step$value[0], callbacks = _step$value[1]; if (!_pred.apply(_this, [exports])) continue; callbacks.forEach(function (cb) { return cb(exports, args); }); callbacksMap.delete(_pred); !callbacksMap.size && (_this._hookModuleCall = null); break; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return !callbacksMap.size; }); this._hookModuleCall = function (cb, pred) { if (callbacksMap.has(pred)) { callbacksMap.get(pred).push(cb); } else { callbacksMap.set(pred, [cb]); } }; } }, { key: '_isUpsModuleCall', value: function _isUpsModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('getServieceUrl') && /\.id\s*=\s*"ups"/.test(exports.default.toString()); } }, { key: 'hookUps', value: function hookUps(cb) { this._hookModuleCall(cb, this._isUpsModuleCall); } }, { key: 'hookUpsOnComplete', value: function hookUpsOnComplete(cb) { this.hookUps(function (exports) { var onComplete = exports.default.prototype.onComplete; exports.default.prototype.onComplete = function (res) { cb(res); onComplete.apply(this, [res]); }; }); } }, { key: '_isLogoModuleCall', value: function _isLogoModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('reset') && /logo\.style\.display/.test(exports.default.prototype.reset.toString()); } }, { key: 'hookLogo', value: function hookLogo(cb) { this._hookModuleCall(cb, this._isLogoModuleCall); } }, { key: '_isQualityIconComponentModuleCall', value: function _isQualityIconComponentModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('renderQuality'); } }, { key: 'hookQualityIcon', value: function hookQualityIcon(cb) { this._hookModuleCall(cb, this._isQualityIconComponentModuleCall); } }, { key: 'hookRenderQuality', value: function hookRenderQuality(cb) { Hooker.hookQualityIcon(function (exports) { var renderQuality = exports.default.prototype.renderQuality; exports.default.prototype.renderQuality = function (langCode) { cb(langCode, this); renderQuality.apply(this, [langCode]); }; }); } }, { key: 'hookSetQuality', value: function hookSetQuality(cb) { Hooker.hookQualityIcon(function (exports) { var setQuality = exports.default.prototype.setQuality; exports.default.prototype.setQuality = function () { for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } // quality, innerText cb(args, this); setQuality.apply(this, args); }; }); } }, { key: '_isManageModuleCall', value: function _isManageModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_resetPlayer'); } }, { key: 'hookManage', value: function hookManage(cb) { this._hookModuleCall(cb, this._isManageModuleCall); } }, { key: 'hookInitPlayerEvent', value: function hookInitPlayerEvent(cb) { Hooker.hookManage(function (exports) { var _initPlayerEvent = exports.default.prototype._initPlayerEvent; exports.default.prototype._initPlayerEvent = function () { cb(this); _initPlayerEvent.apply(this); }; }); } }, { key: 'hookResetPlayerAfter', value: function hookResetPlayerAfter(cb) { Hooker.hookManage(function (exports) { var _resetPlayer = exports.default.prototype._resetPlayer; exports.default.prototype._resetPlayer = function () { try { _resetPlayer.apply(this); } catch (err) { // 忽略 ykSDK.destroyAd 异常 if (!err.stack.includes('destroyAd')) throw err; } cb(this); }; }); } }, { key: '_isKeyShortcutsModuleCall', value: function _isKeyShortcutsModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('registerEvents'); } }, { key: 'hookKeyShortcuts', value: function hookKeyShortcuts(cb) { this._hookModuleCall(cb, this._isKeyShortcutsModuleCall); } }, { key: '_isTipsModuleCall', value: function _isTipsModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showHintTips'); } }, { key: 'hookTips', value: function hookTips(cb) { this._hookModuleCall(cb, this._isTipsModuleCall); } }, { key: '_isAdServiceModuleCall', value: function _isAdServiceModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('requestAdData'); } }, { key: 'hookAdService', value: function hookAdService(cb) { this._hookModuleCall(cb, this._isAdServiceModuleCall); } }, { key: '_isTopAreaModuleCall', value: function _isTopAreaModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_timerHandler'); } }, { key: 'hookTopArea', value: function hookTopArea(cb) { this._hookModuleCall(cb, this._isTopAreaModuleCall); } }, { key: 'hookTopAreaAddEvent', value: function hookTopAreaAddEvent(cb) { Hooker.hookTopArea(function (exports) { var _addEvent = exports.default.prototype._addEvent; exports.default.prototype._addEvent = function () { cb(this); _addEvent.apply(this); }; }); } }, { key: '_isPreviewLayerModuleCall', value: function _isPreviewLayerModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setPreviewShow'); } }, { key: 'hookPreviewLayer', value: function hookPreviewLayer(cb) { this._hookModuleCall(cb, this._isPreviewLayerModuleCall); } }, { key: 'hookPreviewLayerBind', value: function hookPreviewLayerBind(cb) { Hooker.hookPreviewLayer(function (exports) { var bind = exports.default.prototype.bind; exports.default.prototype.bind = function () { cb(this); bind.apply(this); }; }); } }, { key: '_isSettingSeriesComponentModuleCall', value: function _isSettingSeriesComponentModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_addEvent') && exports.default.prototype._addEvent.toString().includes('seriesliseLayer'); } }, { key: 'hookSettingSeries', value: function hookSettingSeries(cb) { this._hookModuleCall(cb, this._isSettingSeriesComponentModuleCall); } }, { key: '_isSettingsIconComponentModuleCall', value: function _isSettingsIconComponentModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setConfig'); } }, { key: 'hookSettingsIcon', value: function hookSettingsIcon(cb) { this._hookModuleCall(cb, this._isSettingsIconComponentModuleCall); } }, { key: '_isTriggerLayerComponentModuleCall', value: function _isTriggerLayerComponentModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showMenu'); } }, { key: 'hookTriggerLayer', value: function hookTriggerLayer(cb) { this._hookModuleCall(cb, this._isTriggerLayerComponentModuleCall); } }, { key: '_isUtilModuleCall', value: function _isUtilModuleCall(exports) { return exports.setLocalData && exports.getLocalData; } }, { key: 'hookUtil', value: function hookUtil(cb) { this._hookModuleCall(cb, this._isUtilModuleCall); } }, { key: '_isGlobalModuleCall', value: function _isGlobalModuleCall(exports) { return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('resetConfig'); } }, { key: 'hookGlobal', value: function hookGlobal(cb) { this._hookModuleCall(cb, this._isGlobalModuleCall); } }, { key: 'hookGlobalConstructorAfter', value: function hookGlobalConstructorAfter(cb) { Hooker.hookGlobal(function (exports) { var constructor = exports.default; exports.default = function () { for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { args[_key8] = arguments[_key8]; } constructor.apply(this, args); cb(this); }; exports.default.prototype = constructor.prototype; }); } }, { key: 'hookGlobalInit', value: function hookGlobalInit(cb) { Hooker.hookGlobal(function (exports) { var init = exports.default.prototype.init; exports.default.prototype.init = function (config) { cb(config, this); init.apply(this, [config]); }; }); } }, { key: 'hookGlobalDeal', value: function hookGlobalDeal(cb) { Hooker.hookGlobal(function (exports) { var deal = exports.default.prototype.deal; exports.default.prototype.deal = function () { cb(this); deal.apply(this); }; }); } }, { key: 'hookGlobalResetAfter', value: function hookGlobalResetAfter(cb) { Hooker.hookGlobal(function (exports) { var reset = exports.default.prototype.reset; exports.default.prototype.reset = function () { reset.apply(this); cb(this); }; }); } }, { key: '_extractArgsName', value: function _extractArgsName(code) { return code.slice(code.indexOf('(') + 1, code.indexOf(')')).split(/\s*,\s*/); } }, { key: '_extractFunctionBody', value: function _extractFunctionBody(code) { return code.slice(code.indexOf('{') + 1, code.lastIndexOf('}')); } }, { key: '_isBaseModuleCall', value: function _isBaseModuleCall(exports) { return exports.SingleVideoControl && exports.MultiVideoControl; } }, { key: 'hookBase', value: function hookBase(cb, mode) { var _this2 = this; var callbacks = []; var codeCallbacks = []; (mode === 'code' ? codeCallbacks : callbacks).push(cb); this._hookModuleCall(function (exports, args) { if (codeCallbacks.length > 0) { var code = args[3].m[args[1].i].toString(); code = codeCallbacks.reduce(function (c, cb) { return cb(c); }, code); var fn = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(_this2._extractArgsName(code)), [_this2._extractFunctionBody(code)])))(); fn.apply(args[0], args.slice(1)); } callbacks.forEach(function (cb) { return cb(args[1].exports); }); _this2.hookBase = null; }, this._isBaseModuleCall); this.hookBase = function (cb, mode) { return (mode === 'code' ? codeCallbacks : callbacks).push(cb); }; } }, { key: 'hookGlobalVariable', value: function hookGlobalVariable(name, cb) { var window = unsafeWindow; var value = window[name]; Object.defineProperty(window, name, { get: function get() { return value; }, set: function set(v) { try { var ret = cb(v); value = ret === undefined ? v : ret; } catch (err) { Logger.error(err.stack); } } }); if (value) window[name] = value; } }, { key: 'hookOz', value: function hookOz(cb) { var callbacks = [cb]; this.hookGlobalVariable('oz', function (oz) { callbacks.forEach(function (cb) { return cb(oz); }); }); this.hookOz = function (cb) { return callbacks.push(cb); }; } }, { key: 'hookDefine', value: function hookDefine(name, cb) { var _this3 = this; var callbacksMap = new Map([[name, [cb]]]); this.hookOz(function (oz) { var self = _this3; var define = oz.define; oz.define = function (name, deps, block) { if (callbacksMap.has(name)) { var code = block.toString(); code = callbacksMap.get(name).reduce(function (c, cb) { return cb(c); }, code); block = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(self._extractArgsName(code)), [self._extractFunctionBody(code)])))(); } define(name, deps, block); }; }); this.hookDefine = function (name, cb) { if (callbacksMap.has(name)) { callbacksMap.get(name).push(cb); } else { callbacksMap.set(name, [cb]); } }; } }]); return Hooker; }(); var Patch = function () { function Patch() { _classCallCheck(this, Patch); this._installed = false; } _createClass(Patch, [{ key: 'install', value: function install() { if (!this._installed) { this._installed = true; this._apply(); } } }, { key: '_apply', value: function _apply() {} }]); return Patch; }(); var MockAdsPatch = function (_Patch) { _inherits(MockAdsPatch, _Patch); function MockAdsPatch() { _classCallCheck(this, MockAdsPatch); return _possibleConstructorReturn(this, (MockAdsPatch.__proto__ || Object.getPrototypeOf(MockAdsPatch)).call(this)); } _createClass(MockAdsPatch, [{ key: '_apply', value: function _apply() { var self = this; Hooker.hookAdService(function (exports) { exports.default.prototype.requestAdData = function (obj /* , params */) { var _this5 = this; setTimeout(function () { if ('frontad' === obj.adtype) { _this5.success(obj, self._fakeFrontAdData()); } else { _this5.fail(obj, { code: '404', message: 'error' }); } }, 0); }; }); this._hideOppoAds(); } }, { key: '_fakeFrontAdData', value: function _fakeFrontAdData() { var data = { VAL: [] }; return data; } }, { key: '_hideOppoAds', value: function _hideOppoAds() { GM_addStyle('\n .oppo-ads, .oppinfo {\n display: none !important;\n }\n '); } }]); return MockAdsPatch; }(Patch); var WatermarksPatch = function (_Patch2) { _inherits(WatermarksPatch, _Patch2); function WatermarksPatch() { _classCallCheck(this, WatermarksPatch); return _possibleConstructorReturn(this, (WatermarksPatch.__proto__ || Object.getPrototypeOf(WatermarksPatch)).call(this)); } _createClass(WatermarksPatch, [{ key: '_apply', value: function _apply() { Hooker.hookLogo(function (exports) { exports.default.prototype.reset = function () {}; }); } }]); return WatermarksPatch; }(Patch); var VipPatch = function (_Patch3) { _inherits(VipPatch, _Patch3); function VipPatch() { _classCallCheck(this, VipPatch); return _possibleConstructorReturn(this, (VipPatch.__proto__ || Object.getPrototypeOf(VipPatch)).call(this)); } _createClass(VipPatch, [{ key: '_apply', value: function _apply() { Hooker.hookUpsOnComplete(function (res) { var data = res.data; data.user = Object.assign(data.user || {}, { vip: true }); data.vip = Object.assign(data.vip || {}, { hd3: true }); }); } }]); return VipPatch; }(Patch); var QualityPatch = function (_Patch4) { _inherits(QualityPatch, _Patch4); function QualityPatch() { _classCallCheck(this, QualityPatch); return _possibleConstructorReturn(this, (QualityPatch.__proto__ || Object.getPrototypeOf(QualityPatch)).call(this)); } _createClass(QualityPatch, [{ key: '_apply', value: function _apply() { this._improveAdaptQuality(); } }, { key: '_findBestQuality', value: function _findBestQuality(qualityList) { return ['1080p', '720p', '480p', '320p'].find(function (q) { return qualityList.some(function (v) { return v === q; }); }); } }, { key: '_improveAdaptQuality', value: function _improveAdaptQuality() { var self = this; Hooker.hookGlobal(function (exports) { var adaptQuality = exports.default.prototype.adaptQuality; exports.default.prototype.adaptQuality = function (lang) { var cfg = this._config; var quality = cfg.quality; adaptQuality.apply(this, [lang]); if (!this.qualityList.includes(quality)) { cfg.quality = self._findBestQuality(this.qualityList); } }; }); } }]); return QualityPatch; }(Patch); var DashboardPatch = function (_Patch5) { _inherits(DashboardPatch, _Patch5); function DashboardPatch() { _classCallCheck(this, DashboardPatch); return _possibleConstructorReturn(this, (DashboardPatch.__proto__ || Object.getPrototypeOf(DashboardPatch)).call(this)); } _createClass(DashboardPatch, [{ key: '_apply', value: function _apply() { this._prepare(); this._patch(); } }, { key: '_prepare', value: function _prepare() { this._exposeDashboard(); Hooker.hookPreviewLayerBind(function (that) { that._el.addEventListener('mouseover', function () { return that.emit('mouseoverpreview'); }); that._el.addEventListener('mouseleave', function () { return that.emit('mouseleavepreview'); }); }); } }, { key: '_findVarName', value: function _findVarName(code) { return (/"dashboard"\s*,\s*(\w+)/.exec(code)[1] ); } }, { key: '_exposeDashboard', value: function _exposeDashboard() { var _this10 = this; Hooker.hookBase(function (code) { var varName = _this10._findVarName(code); return code.replace(/\.exports\s*=\s*(\w+)/, '$&;$1.__Dashboard=' + varName + ';'); }, 'code'); } }, { key: '_patch', value: function _patch() { Hooker.hookBase(function (exports) { var proto = exports.__Dashboard.prototype; proto.bindAutoHide = function () { var _this11 = this; this._args.show = 'function' === typeof this._args.show ? this._args.show : function () {}; this._args.hide = 'function' === typeof this._args.hide ? this._args.show : function () {}; this._el.addEventListener('mouseover', function () { return _this11._mouseover = true; }); this._el.addEventListener('mouseleave', function () { return _this11._mouseover = false; }); this.on('mouseoverpreview', function () { return _this11._mouseoverpreview = true; }); this.on('mouseleavepreview', function () { return _this11._mouseoverpreview = false; }); this._video.on('play', function () { if (!_this11._mouseover && !_this11._mouseoverpreview) _this11._hideTimeout = setTimeout(_this11.hide.bind(_this11), _this11._args.autoHide); }); this._video.on('pause', function () { _this11._hideTimeout && clearTimeout(_this11._hideTimeout); _this11.isShow() || _this11.show(); }); this._parent.addEventListener('mousemove', function () { _this11._hideTimeout && clearTimeout(_this11._hideTimeout); _this11.isShow() || _this11.show(); if (!_this11._isPaused() && !_this11._mouseover && !_this11._mouseoverpreview) _this11._hideTimeout = setTimeout(_this11.hide.bind(_this11), _this11._args.autoHide); }); this._parent.addEventListener('mouseleave', function () { _this11._hideTimeout && clearTimeout(_this11._hideTimeout); if (!_this11._isPaused()) _this11.hide(); }); }; proto._isPaused = function () { return this._video._videoCore.video.paused; }; proto.isShow = function () { return this._el.style.display !== 'none'; }; proto.show = function () { this.emit('dashboardshow'); this._parent.style.cursor = ''; this._el.style.display = ''; this._args.show(); }; proto.hide = function () { this.emit('dashboardhide'); this._parent.style.cursor = 'none'; // 隐藏鼠标 this._el.style.display = 'none'; this._args.show(); }; }); } }]); return DashboardPatch; }(Patch); var TopAreaPatch = function (_Patch6) { _inherits(TopAreaPatch, _Patch6); function TopAreaPatch() { _classCallCheck(this, TopAreaPatch); return _possibleConstructorReturn(this, (TopAreaPatch.__proto__ || Object.getPrototypeOf(TopAreaPatch)).call(this)); } _createClass(TopAreaPatch, [{ key: '_apply', value: function _apply() { Hooker.hookTopAreaAddEvent(function (that) { that.on('webfullscreen', function (isWebFullscreen) { isWebFullscreen ? that._showHideTop(true) : that._hideHideTop(); }); that.on('dashboardshow', function () { var playerState = that._video.global.playerState; if (playerState.fullscreen || playerState.webfullscreen) { that._showHideTop(true); } }); that.on('dashboardhide', function () { var playerState = that._video.global.playerState; if (playerState.fullscreen || playerState.webfullscreen) { that._hideHideTop(); } }); }); Hooker.hookResetPlayerAfter(function (that) { // 网页全屏播放上下集重置播放器后显示顶部控件 if (!that.global.playerState.fullscreen) that._player.control.emit('webfullscreen', that.global.playerState.webfullscreen); }); } }]); return TopAreaPatch; }(Patch); var SettingSeriesPatch = function (_Patch7) { _inherits(SettingSeriesPatch, _Patch7); function SettingSeriesPatch() { _classCallCheck(this, SettingSeriesPatch); return _possibleConstructorReturn(this, (SettingSeriesPatch.__proto__ || Object.getPrototypeOf(SettingSeriesPatch)).call(this)); } _createClass(SettingSeriesPatch, [{ key: '_apply', value: function _apply() { Hooker.hookSettingSeries(function (exports) { // 网页全屏显示选集 var _addEvent = exports.default.prototype._addEvent; exports.default.prototype._addEvent = function () { var _this14 = this; _addEvent.apply(this); this.on('webfullscreen', function (isWebFullscreen) { if (isWebFullscreen) { if (_this14.seriesList.length > 1) _this14._el.style.display = 'inline-block'; } else { _this14._el.style.display = 'none'; _this14._el.classList.remove('cliced'); _this14.emit('seriesliseLayer', false); } }); }; }); } }]); return SettingSeriesPatch; }(Patch); var ContinuePlayPatch = function (_Patch8) { _inherits(ContinuePlayPatch, _Patch8); function ContinuePlayPatch() { _classCallCheck(this, ContinuePlayPatch); return _possibleConstructorReturn(this, (ContinuePlayPatch.__proto__ || Object.getPrototypeOf(ContinuePlayPatch)).call(this)); } _createClass(ContinuePlayPatch, [{ key: '_apply', value: function _apply() { var _this16 = this; Hooker.hookInitPlayerEvent(function (that) { // 视频播放结束处理 that._player.control.on('ended', that._onEnd.bind(that)); that._player.control.on('ended', function () { return _this16._onEnd(that); }); }); } }, { key: '_onEnd', value: function _onEnd(that) { var config = that.global.config; var playerState = that.global.playerState; if (config.continuePlay && config.nextVid && !playerState.fullscreen) { if (playerState.webfullscreen) { that.playByVid({ vid: that.global.config.nextVid }); } else { that.gotoVideo(that.global.config.nextVid); } } } }]); return ContinuePlayPatch; }(Patch); var FullscreenPatch = function (_Patch9) { _inherits(FullscreenPatch, _Patch9); function FullscreenPatch() { _classCallCheck(this, FullscreenPatch); return _possibleConstructorReturn(this, (FullscreenPatch.__proto__ || Object.getPrototypeOf(FullscreenPatch)).call(this)); } _createClass(FullscreenPatch, [{ key: '_apply', value: function _apply() { Object.defineProperty(document, 'fullscreen', {}); } }]); return FullscreenPatch; }(Patch); var WebFullscreen = function () { function WebFullscreen(elem) { _classCallCheck(this, WebFullscreen); this._elem = elem; } _createClass(WebFullscreen, [{ key: 'isWebFullscreen', value: function isWebFullscreen() { return this._elem.classList.contains('webfullscreen'); } }, { key: 'enter', value: function enter() { this._elem.classList.add('webfullscreen'); var body = document.body; body.style.overflow = 'hidden'; var parentElement = this._elem.parentElement; while (parentElement && parentElement !== body) { parentElement.classList.add('z-top'); parentElement = parentElement.parentElement; } } }, { key: 'exit', value: function exit() { this._elem.classList.remove('webfullscreen'); var body = document.body; body.style.overflow = ''; var parentElement = this._elem.parentElement; while (parentElement && parentElement !== body) { parentElement.classList.remove('z-top'); parentElement = parentElement.parentElement; } } }, { key: 'toggle', value: function toggle() { this.isWebFullscreen() ? this.exit() : this.enter(); } }], [{ key: 'addStyle', value: function addStyle() { GM_addStyle('\n .z-top {\n position: relative !important;\n z-index: 23333333 !important;\n }\n .webfullscreen {\n display: block !important;\n position: fixed !important;\n width: 100% !important;\n height: 100% !important;\n top: 0 !important;\n left: 0 !important;\n background: #000 !important;\n z-index: 23333333 !important;\n }\n '); } }]); return WebFullscreen; }(); var ManagePatch = function (_Patch10) { _inherits(ManagePatch, _Patch10); function ManagePatch() { _classCallCheck(this, ManagePatch); return _possibleConstructorReturn(this, (ManagePatch.__proto__ || Object.getPrototypeOf(ManagePatch)).call(this)); } _createClass(ManagePatch, [{ key: '_apply', value: function _apply() { this._prepare(); this._hookManage(); } }, { key: '_prepare', value: function _prepare() { this._customTip(); this._disablePlayAfterSeek(); this._addPrevInfo(); this._playAfterPlayerReset(); this._keepPlaybackRate(); this._playbackRatePersistence(); new ContinuePlayPatch().install(); new FullscreenPatch().install(); } }, { key: '_customTip', value: function _customTip() { Hooker.hookTips(function (exports) { var showHintTips = exports.default.prototype.showHintTips; exports.default.prototype.showHintTips = function (code, info) { if (info.msg) { this._hintLayer.setHintShow(info.msg); } else { showHintTips.apply(this, [code, info]); } }; }); } }, { key: '_disablePlayAfterSeek', value: function _disablePlayAfterSeek() { // SingleVideoControl seek 后不自动播放 Hooker.hookBase(function (exports) { var _setCurrentTime = exports.SingleVideoControl.prototype._setCurrentTime; exports.SingleVideoControl.prototype._setCurrentTime = function (time) { var play = this.video.play; this.video.play = function () {}; _setCurrentTime.apply(this, [time]); this.video.play = play; }; }); } }, { key: '_keepPlaybackRate', value: function _keepPlaybackRate() { Hooker.hookBase(function (exports) { var proto = exports.MultiVideoControl.prototype; var _setVideo = proto._setVideo; proto._setVideo = function () { var rate = this.video.playbackRate; for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { args[_key9] = arguments[_key9]; } _setVideo.apply(this, args); this.video.playbackRate = rate; }; }); } }, { key: '_playbackRatePersistence', value: function _playbackRatePersistence() { var util = void 0; Hooker.hookUtil(function (exports) { return util = exports; }); Hooker.hookSettingsIcon(function (exports) { var proto = exports.default.prototype; var setDataUI = proto.setDataUI; proto.setDataUI = function (data) { var _this19 = this; setDataUI.apply(this, [data]); this._video.global.playerState = { playbackRate: data.playbackRate || 1 }; this.on('playbackratechange', function (rate) { _this19.data.playbackRate = rate; util.setLocalData('YK_PSL_SETTINGS', _this19.data); }); }; }); } }, { key: '_addPrevInfo', value: function _addPrevInfo() { Hooker.hookGlobalDeal(function (that) { if (that.ups && that.ups.videoData && that.ups.programList && that.ups.programList.videoList) { var list = that.ups.programList.videoList; var currVid = that.ups.videoData.id; var currIdx = list.findIndex(function (item) { return parseInt(item.vid) === currVid; }); if (currIdx > 0) { var prevVideo = list[currIdx - 1]; that.ups.programList.prevVideo = prevVideo; prevVideo && (that._config.prevVid = prevVideo.encodevid); } } }); } }, { key: '_playAfterPlayerReset', value: function _playAfterPlayerReset() { Hooker.hookResetPlayerAfter(function (that) { if (that.global.playerState.state === 'playerreset') that.play(); }); } }, { key: '_hookManage', value: function _hookManage() { Hooker.hookManage(this._hookManageCallback.bind(this)); } }, { key: '_hookManageCallback', value: function _hookManageCallback(exports) { var proto = exports.default.prototype; var _init = proto._init; proto._init = function () { _init.apply(this); WebFullscreen.addStyle(); this._webfullscreen = new WebFullscreen(this.container); }; proto._showTip = function (msg) { this._emitter.emit('player.showinfo', { type: 'hint', msg: msg }); }; proto.play = function () { this._player && this._player.control.play(); this._showTip('播放'); }; proto._pause = proto.pause; proto.pause = function () { this._pause(); this._showTip('暂停'); }; proto.adjustVolume = function (value) { var volume = this.global.playerState.volume + value; volume = Math.max(0, Math.min(1, volume.toFixed(2))); this._player.control.setVolume(volume); if (volume === 0) { this._emitter.emit('player.showinfo', { type: 'hint', code: 'H0003', volume: volume + '%' }); } }; proto.toggleMute = function () { if (this.global.playerState.muted) this._showTip('取消静音'); this.setMuted(!this.global.playerState.muted); }; proto.stepSeek = function (stepTime) { var duration = this._player.control.getDuration(); var currentTime = this.global.currentTime; var seekTime = Math.max(0, Math.min(duration, currentTime + stepTime)); this.seek(seekTime); var msg = void 0; if (Math.abs(stepTime) < 60) { msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime + '\u79D2' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) + '\u79D2'; } else { msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime / 60 + '\u5206\u949F' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) / 60 + '\u5206\u949F'; } this._showTip(msg); }; proto.rangeSeek = function (range) { var duration = this._player.control.getDuration(); var seekTime = Math.max(0, Math.min(duration, duration * range)); this.seek(seekTime); this._showTip('定位:' + (range * 100).toFixed(0) + '%'); }; proto.isFullscreen = function () { return this.global.playerState.fullscreen; }; proto.toggleFullscreen = function () { if (this.isFullscreen()) { this.exitFullscreen(); } else { this.fullScreen(); } }; proto.isWebFullscreen = function () { return this._webfullscreen.isWebFullscreen(); }; proto.enterWebFullscreen = function () { this._webfullscreen.enter(); this.global.playerState = { webfullscreen: true }; this._player.control.emit('webfullscreen', true); }; proto.exitWebFullscreen = function () { this._webfullscreen.exit(); this.global.playerState = { webfullscreen: false }; this._player.control.emit('webfullscreen', false); }; proto.toggleWebFullscreen = function () { this.isWebFullscreen() ? this.exitWebFullscreen() : this.enterWebFullscreen(); }; proto.setRate = function (rate) { var videoCore = this._player.control._videoCore; var video = videoCore.video; if (this._player.config.controlType === 'multi') { videoCore._videoElments.forEach(function (v) { return v.playbackRate = rate; }); } else { video.playbackRate = rate; } }; proto.adjustPlaybackRate = function (value) { var video = this._player.control._videoCore.video; var rate = Math.max(0.2, Math.min(5, parseFloat((video.playbackRate + value).toFixed(1)))); this.setRate(rate); this.global.playerState = { playbackRate: rate }; this._player.control.emit('playbackratechange', rate); this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate); }; proto.turnPlaybackRate = function () { var video = this._player.control._videoCore.video; var rate = video.playbackRate !== 1 ? 1 : this.global.playerState.playbackRate; this.setRate(rate); this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate); }; proto.getFps = function () { return 25; // 标清fps为15,标清以上fps为25。 }; proto.prevFrame = function () { var state = this.global.playerState.state; if (state === 'playing') this.pause(); var duration = this._player.control.getDuration(); var currentTime = this.global.currentTime; var seekTime = Math.max(0, Math.min(duration, currentTime - 1 / this.getFps())); this.seek(seekTime); this._showTip('上一帧'); }; proto.nextFrame = function () { var state = this.global.playerState.state; if (state === 'playing') this.pause(); var duration = this._player.control.getDuration(); var currentTime = this.global.currentTime; var seekTime = Math.max(0, Math.min(duration, currentTime + 1 / this.getFps())); this.seek(seekTime); this._showTip('下一帧'); }; proto.playPrev = function () { var prevVid = this.global.config.prevVid; if (prevVid) { if (this.isFullscreen() || this.isWebFullscreen()) { this.playByVid({ vid: prevVid }); } else { this.gotoVideo(prevVid); } this._showTip('播放上一集'); } else { this._showTip('没有上一集哦'); } }; var playNext = proto.playNext; proto.playNext = function (data) { if (data) return playNext.apply(this, [data]); var nextVid = this.global.config.nextVid; if (nextVid) { if (this.isFullscreen() || this.isWebFullscreen()) { this.playByVid({ vid: nextVid }); } else { this.gotoVideo(nextVid); } this._showTip('播放下一集'); } else { this._showTip('没有下一集哦'); } }; proto.gotoVideo = function (vid) { location.href = '//v.youku.com/v_show/id_' + vid + '.html'; }; } }]); return ManagePatch; }(Patch); var managePatch = new ManagePatch(); var KeyShortcutsPatch = function (_Patch11) { _inherits(KeyShortcutsPatch, _Patch11); function KeyShortcutsPatch() { _classCallCheck(this, KeyShortcutsPatch); return _possibleConstructorReturn(this, (KeyShortcutsPatch.__proto__ || Object.getPrototypeOf(KeyShortcutsPatch)).call(this)); } _createClass(KeyShortcutsPatch, [{ key: '_apply', value: function _apply() { this._prepare(); this._addListener(); } }, { key: '_prepare', value: function _prepare() { managePatch.install(); this._obtainPlayer(); } }, { key: '_obtainPlayer', value: function _obtainPlayer() { var self = this; Hooker.hookKeyShortcuts(function (exports) { exports.default.prototype.registerEvents = function () { self._player = this._player; }; }); } }, { key: '_addListener', value: function _addListener() { document.addEventListener('keydown', this._handler.bind(this)); } }, { key: '_handler', value: function _handler(event) { if (event.target.nodeName !== 'BODY') return; switch (event.keyCode) { case 32: // Spacebar if (!event.ctrlKey && !event.shiftKey && !event.altKey) { var state = this._player.global.playerState.state; if (state === 'paused') { this._player.play(); } else if (state === 'ended') { this._player.replay(); } else { this._player.pause(); } } else { return; } break; case 39: // → Arrow Right case 37: { // ← Arrow Left var stepTime = void 0; if (!event.ctrlKey && !event.shiftKey && !event.altKey) { stepTime = 39 === event.keyCode ? 5 : -5; } else if (event.ctrlKey && !event.shiftKey && !event.altKey) { stepTime = 39 === event.keyCode ? 30 : -30; } else if (!event.ctrlKey && event.shiftKey && !event.altKey) { stepTime = 39 === event.keyCode ? 60 : -60; } else if (event.ctrlKey && !event.shiftKey && event.altKey) { stepTime = 39 === event.keyCode ? 3e2 : -3e2; // 5分钟 } else { return; } this._player.stepSeek(stepTime); break; } case 38: // ↑ Arrow Up case 40: // ↓ Arrow Down if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.adjustVolume(38 === event.keyCode ? 0.05 : -0.05); } else { return; } break; case 77: // M if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.toggleMute(); } else { return; } break; case 13: // Enter if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.toggleFullscreen(); } else if (event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.toggleWebFullscreen(); } else { return; } break; case 67: // C case 88: // X if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.adjustPlaybackRate(67 === event.keyCode ? 0.1 : -0.1); } else { return; } break; case 90: // Z if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.turnPlaybackRate(); } else { return; } break; case 68: // D case 70: // F if (!event.ctrlKey && !event.shiftKey && !event.altKey) { if (event.keyCode === 68) { this._player.prevFrame(); } else { this._player.nextFrame(); } } else { return; } break; case 80: // P case 78: // N if (!event.ctrlKey && event.shiftKey && !event.altKey) { if (event.keyCode === 78) { this._player.playNext(); } else { this._player.playPrev(); } } else { return; } break; case 27: // ESC if (!event.ctrlKey && !event.shiftKey && !event.altKey) this._player.isWebFullscreen() && this._player.exitWebFullscreen(); return; default: if (event.keyCode >= 48 && event.keyCode <= 57) { // 0 ~ 9 if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this._player.rangeSeek((event.keyCode - 48) * 0.1); } else { return; } } else { return; } } event.preventDefault(); event.stopPropagation(); } }]); return KeyShortcutsPatch; }(Patch); var MouseShortcutsPatch = function (_Patch12) { _inherits(MouseShortcutsPatch, _Patch12); function MouseShortcutsPatch() { _classCallCheck(this, MouseShortcutsPatch); return _possibleConstructorReturn(this, (MouseShortcutsPatch.__proto__ || Object.getPrototypeOf(MouseShortcutsPatch)).call(this)); } _createClass(MouseShortcutsPatch, [{ key: '_apply', value: function _apply() { this._prepare(); this._initEvents(); } }, { key: '_prepare', value: function _prepare() { managePatch.install(); } }, { key: '_initEvents', value: function _initEvents() { Hooker.hookTriggerLayer(function (exports) { var proto = exports.default.prototype; var initEvents = proto.initEvents; proto.initEvents = function () { var _this22 = this; var player = this._video.ykplayer; this._el.addEventListener('dblclick', function (event) { if (event.ctrlKey) { player.toggleWebFullscreen(); event.stopImmediatePropagation(); _this22._clickTimer.clear(); } }); this._el.addEventListener('wheel', function (event) { if (player.isFullscreen() || player.isWebFullscreen()) { var delta = event.wheelDelta || event.detail || event.deltaY && -event.deltaY; player.adjustVolume(delta > 0 ? 0.05 : -0.05); } }); initEvents.apply(this); }; }); } }]); return MouseShortcutsPatch; }(Patch); var ShortcutsPatch = function (_Patch13) { _inherits(ShortcutsPatch, _Patch13); function ShortcutsPatch() { _classCallCheck(this, ShortcutsPatch); return _possibleConstructorReturn(this, (ShortcutsPatch.__proto__ || Object.getPrototypeOf(ShortcutsPatch)).call(this)); } _createClass(ShortcutsPatch, [{ key: '_apply', value: function _apply() { new KeyShortcutsPatch().install(); Logger.log('添加键盘快捷键'); new MouseShortcutsPatch().install(); Logger.log('添加鼠标快捷键'); } }]); return ShortcutsPatch; }(Patch); var TVBH5Patch = function (_Patch14) { _inherits(TVBH5Patch, _Patch14); function TVBH5Patch() { _classCallCheck(this, TVBH5Patch); return _possibleConstructorReturn(this, (TVBH5Patch.__proto__ || Object.getPrototypeOf(TVBH5Patch)).call(this)); } _createClass(TVBH5Patch, [{ key: '_apply', value: function _apply() { Hooker.hookGlobalVariable('PageConfig', function (cfg) { Object.defineProperty(cfg, 'production', { get: function get() { return ''; } }); }); Logger.log('H5-player has been enabled at TVB\'s videos.'); } }]); return TVBH5Patch; }(Patch); // class H5Patch extends Patch { // constructor() { // super(); // } // _apply() { // Hooker.hookDefine('page/find/play/player/load', this._forceH5.bind(this)); // } // _forceH5(code) { // return code.replace(/(if\s*\().*?(\)\s*\{)/, '$1true$2').replace('window.sessionStorage', 'null'); // } // } function ensureH5PlayerEnabled() { // (new H5Patch()).install(); Object.defineProperty(unsafeWindow.navigator, 'plugins', { get: function get() { return {}; } }); Logger.log('启用html5播放器'); } function mockAds() { new MockAdsPatch().install(); Logger.log('和谐广告'); } function invalidateWatermarks() { new WatermarksPatch().install(); Logger.log('和谐水印'); } function invalidateQualityLimitation() { new VipPatch().install(); Logger.log('解除会员画质限制'); } function improveQualityLogic() { new QualityPatch().install(); Logger.log('改善画质逻辑'); } function improveAutoHide() { new DashboardPatch().install(); new TopAreaPatch().install(); new SettingSeriesPatch().install(); Logger.log('改善控件与光标自动隐藏'); } function improveShortcuts() { new ShortcutsPatch().install(); } function enableH5ForTVB() { new TVBH5Patch().install(); } //============================================================================= ensureH5PlayerEnabled(); mockAds(); invalidateWatermarks(); invalidateQualityLimitation(); improveQualityLogic(); improveAutoHide(); improveShortcuts(); enableH5ForTVB(); })();