'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 _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // ==UserScript== // @name iqiyi-player-switch // @namespace https://github.com/gooyie/userscript-iqiyi-player-switch // @homepageURL https://github.com/gooyie/userscript-iqiyi-player-switch // @supportURL https://github.com/gooyie/userscript-iqiyi-player-switch/issues // @version 1.9.1 // @description 爱奇艺flash播放器与html5播放器随意切换,改善html5播放器播放体验。 // @author gooyie // @license MIT License // // @include *://*.iqiyi.com/* // @include *://v.baidu.com/* // @include *://music.baidu.com/mv/* // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_info // @grant unsafeWindow // @connect qiyi.com // @require https://greasyfork.org/scripts/29319-web-streams-polyfill/code/web-streams-polyfill.js?version=191261 // @require https://greasyfork.org/scripts/29306-fetch-readablestream/code/fetch-readablestream.js?version=191832 // @require https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/3.3.4/adapter.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.7.0/js/md5.min.js // @run-at document-start // @downloadURL none // ==/UserScript== (function () { 'use strict'; var PLAYER_TYPE = { Html5VOD: 'h5_VOD', FlashVOD: 'flash_VOD' }; /* 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: green; font-weight: bolder', 'color: blue'].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 Cookies = function () { function Cookies() { _classCallCheck(this, Cookies); } _createClass(Cookies, null, [{ key: 'get', value: function get(key) { var value = void 0; if (new RegExp('^[^\\x00-\\x20\\x7f\\(\\)<>@,;:\\\\\\"\\[\\]\\?=\\{\\}\\/\\u0080-\\uffff]+$').test(key)) { // eslint-disable-line no-control-regex var re = new RegExp('(^| )' + key + '=([^;]*)(;|$)'); var rs = re.exec(document.cookie); value = rs ? rs[2] : ''; } return value ? decodeURIComponent(value) : ''; } }, { key: 'set', value: function set(k, v) { var o = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var n = o.expires; if ('number' == typeof o.expires) { n = new Date(); n.setTime(n.getTime() + o.expires); } var key = k; var value = encodeURIComponent(v); var path = o.path ? '; path=' + o.path : ''; var expires = n ? '; expires=' + n.toGMTString() : ''; var domain = o.domain ? '; domain=' + o.domain : ''; document.cookie = key + '=' + value + path + expires + domain; } }, { key: 'remove', value: function remove(k) { var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; o.expires = new Date(0); this.set(k, '', o); } }]); return Cookies; }(); var Detector = function () { function Detector() { _classCallCheck(this, Detector); } _createClass(Detector, null, [{ key: 'isSupportHtml5', value: function isSupportHtml5() { var v = document.createElement('video'); return !!(v.canPlayType('audio/mp4; codecs="mp4a.40.2"') && v.canPlayType('video/mp4; codecs="avc1.640029"') && v.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"')); } }, { key: 'isSupportVms', value: function isSupportVms() { return !!(window.MediaSource && window.URL && window.WebSocket && window.ReadableStream && (window.RTCSessionDescription || window.webkitRTCSessionDescription) && (window.RTCPeerConnection || window.webkitRTCPeerConnection) && (window.RTCIceCandidate || window.webkitRTCIceCandidate)); } }, { key: 'isSupportM3u8', value: function isSupportM3u8() { var v = document.createElement('video'); return !!(v.canPlayType('application/x-mpegurl') && v.canPlayType('application/vnd.apple.mpegurl')); } }, { key: 'isChrome', value: function isChrome() { return (/chrome/i.test(navigator.userAgent) ); } }, { key: 'isFirefox', value: function isFirefox() { return (/firefox/i.test(navigator.userAgent) ); } }, { key: 'isEdge', value: function isEdge() { return (/edge/i.test(navigator.userAgent) ); } }, { key: 'isInnerFrame', value: function isInnerFrame() { return window.top !== window.self; } }, { key: 'isOutsite', value: function isOutsite() { return !/\.iqiyi\.com$/.test(location.host); } }, { key: 'hasFlashPlugin', value: function hasFlashPlugin() { var plugins = unsafeWindow.navigator.plugins; return !!(plugins['Shockwave Flash'] && plugins['Shockwave Flash'].description); } }, { key: 'isFullScreen', value: function isFullScreen() { return !!(document.fullscreen || document.webkitIsFullScreen || document.mozFullScreen || document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement); } }]); return Detector; }(); var Hooker = function () { function Hooker() { _classCallCheck(this, Hooker); } _createClass(Hooker, null, [{ key: 'hookCall', value: function hookCall() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; 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.apply(undefined, args); } catch (err) { Logger.error(err.stack); } return ret; }; Function.prototype.call.toString = Function.prototype.call.toLocaleString = function () { return 'function call() { [native code] }'; }; } }, { key: '_isFactoryCall', value: function _isFactoryCall(args) { // module.exports, module, module.exports, require return args.length === 4 && args[1] instanceof Object && args[1].hasOwnProperty('exports'); } }, { key: 'hookFactoryCall', value: function hookFactoryCall() { var _this = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookCall(function () { for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } if (_this._isFactoryCall(args)) cb.apply(undefined, args); }); } }, { key: '_isJqueryFactoryCall', value: function _isJqueryFactoryCall(exports) { return exports.hasOwnProperty('fn') && exports.fn.hasOwnProperty('jquery'); } }, { key: 'hookJquery', value: function hookJquery() { var _this2 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { args[_key8] = arguments[_key8]; } if (_this2._isJqueryFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: 'hookJqueryAjax', value: function hookJqueryAjax() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookJquery(function (exports) { var ajax = exports.ajax.bind(exports); exports.ajax = function (url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if ((typeof url === 'undefined' ? 'undefined' : _typeof(url)) === 'object') { var _ref = [url.url, url]; url = _ref[0]; options = _ref[1]; } var isHijacked = cb(url, options); if (isHijacked) return; return ajax(url, options); }; }); } }, { key: '_isHttpFactoryCall', value: function _isHttpFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return exports.hasOwnProperty('jsonp') && exports.hasOwnProperty('ajax'); } }, { key: 'hookHttp', value: function hookHttp() { var _this3 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { args[_key9] = arguments[_key9]; } if (_this3._isHttpFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: 'hookHttpJsonp', value: function hookHttpJsonp() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookHttp(function (exports) { var jsonp = exports.jsonp.bind(exports); exports.jsonp = function (options) { var isHijacked = cb(options); if (isHijacked) return; return jsonp(options); }; }); } }, { key: '_isLogoFactoryCall', value: function _isLogoFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('showLogo'); } }, { key: 'hookLogo', value: function hookLogo() { var _this4 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len10 = arguments.length, args = Array(_len10), _key10 = 0; _key10 < _len10; _key10++) { args[_key10] = arguments[_key10]; } if (_this4._isLogoFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: '_isFullScreenFactoryCall', value: function _isFullScreenFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return exports.__proto__ && exports.__proto__.hasOwnProperty('isFullScreen'); } }, { key: 'hookFullScreen', value: function hookFullScreen() { var _this5 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len11 = arguments.length, args = Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { args[_key11] = arguments[_key11]; } if (_this5._isFullScreenFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: '_isWebFullScreenFactoryCall', value: function _isWebFullScreenFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return exports.__proto__ && exports.__proto__.hasOwnProperty('isWebFullScreen'); } }, { key: 'hookWebFullScreen', value: function hookWebFullScreen() { var _this6 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len12 = arguments.length, args = Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { args[_key12] = arguments[_key12]; } if (_this6._isWebFullScreenFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: 'hookWebFullScreenInit', value: function hookWebFullScreenInit() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookWebFullScreen(function (exports) { var init = exports.__proto__.init; exports.__proto__.init = function (wrapper, btn) { cb(this, wrapper, btn); init.apply(this, [wrapper, btn]); }; }); } }, { key: '_isPluginControlsFactoryCall', value: function _isPluginControlsFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('initFullScreen'); } }, { key: 'hookPluginControls', value: function hookPluginControls() { var _this7 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len13 = arguments.length, args = Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { args[_key13] = arguments[_key13]; } if (_this7._isPluginControlsFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: 'hookPluginControlsInit', value: function hookPluginControlsInit() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookPluginControls(function (exports) { var init = exports.prototype.init; exports.prototype.init = function () { cb(this); init.apply(this); }; }); } }, { key: 'hookInitFullScreen', value: function hookInitFullScreen() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookPluginControls(function (exports) { var initFullScreen = exports.prototype.initFullScreen; exports.prototype.initFullScreen = function () { cb(this); initFullScreen.apply(this); }; }); } }, { key: '_isCoreFactoryCall', value: function _isCoreFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('getdefaultvds') && exports.prototype.hasOwnProperty('getMovieInfo'); } }, { key: 'hookCore', value: function hookCore() { var _this8 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len14 = arguments.length, args = Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { args[_key14] = arguments[_key14]; } if (_this8._isCoreFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: '_isSkinBaseFactoryCall', value: function _isSkinBaseFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('_checkPlugin'); } }, { key: 'hookSkinBase', value: function hookSkinBase() { var _this9 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len15 = arguments.length, args = Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { args[_key15] = arguments[_key15]; } if (_this9._isSkinBaseFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: '_isPluginHotKeysFactoryCall', value: function _isPluginHotKeysFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('_keydown'); } }, { key: 'hookPluginHotKeys', value: function hookPluginHotKeys() { var _this10 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len16 = arguments.length, args = Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { args[_key16] = arguments[_key16]; } if (_this10._isPluginHotKeysFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: '_isFragmentFactoryCall', value: function _isFragmentFactoryCall() { var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return 'function' === typeof exports && exports.prototype.hasOwnProperty('parseData'); } }, { key: 'hookFragment', value: function hookFragment() { var _this11 = this; var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFactoryCall(function () { for (var _len17 = arguments.length, args = Array(_len17), _key17 = 0; _key17 < _len17; _key17++) { args[_key17] = arguments[_key17]; } if (_this11._isFragmentFactoryCall(args[1].exports)) cb(args[1].exports); }); } }, { key: 'hookParseData', value: function hookParseData() { var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; this.hookFragment(function (exports) { var parseData = exports.prototype.parseData; exports.prototype.parseData = function () { for (var _len18 = arguments.length, args = Array(_len18), _key18 = 0; _key18 < _len18; _key18++) { args[_key18] = arguments[_key18]; } parseData.apply(this, args); cb(this); }; }); } }]); return Hooker; }(); var Faker = function () { function Faker() { _classCallCheck(this, Faker); } _createClass(Faker, null, [{ key: 'fakeMacPlatform', value: function fakeMacPlatform() { var PLAFORM_MAC = 'mac'; Object.defineProperty(unsafeWindow.navigator, 'platform', { get: function get() { return PLAFORM_MAC; } }); } }, { key: 'fakeSafari', value: function fakeSafari() { var UA_SAFARY = 'safari'; Object.defineProperty(unsafeWindow.navigator, 'userAgent', { get: function get() { return UA_SAFARY; } }); } }, { key: 'fakeChrome', value: function fakeChrome() { var UA_CHROME = 'chrome'; Object.defineProperty(unsafeWindow.navigator, 'userAgent', { get: function get() { return UA_CHROME; } }); } }, { key: 'fakeFlashPlugin', value: function fakeFlashPlugin() { var plugin = { description: 'Shockwave Flash 26.0 r0', filename: 'pepflashplayer64_26_0_0_131.dll', length: 0, name: 'Shockwave Flash' }; Reflect.setPrototypeOf(plugin, Plugin.prototype); unsafeWindow.navigator.plugins['Shockwave Flash'] = plugin; } }, { key: '_calcSign', value: function _calcSign(authcookie) { var RESPONSE_KEY = '-0J1d9d^ESd)9jSsja'; return md5(authcookie.substring(5, 39).split('').reverse().join('') + '<1<' + RESPONSE_KEY); } }, { key: 'fakeVipRes', value: function fakeVipRes(authcookie) { var json = { code: 'A00000', data: { sign: this._calcSign(authcookie) } }; return json; } }, { key: 'fakeAdRes', value: function fakeAdRes() { var json = {}; return json; } }, { key: 'fakePassportCookie', value: function fakePassportCookie() { Cookies.set('P00001', 'faked_passport', { domain: '.iqiyi.com' }); Logger.log('faked passport cookie'); } }]); return Faker; }(); var Mocker = function () { function Mocker() { _classCallCheck(this, Mocker); } _createClass(Mocker, null, [{ key: 'mock', value: function mock() { this.mockForBestDefintion(); this.mockAd(); this.mockVip(); this.mockLogo(); this.mockCheckPlugin(); } }, { key: 'mockToUseVms', value: function mockToUseVms() { Faker.fakeChrome(); } }, { key: 'mockToUseM3u8', value: function mockToUseM3u8() { Faker.fakeMacPlatform(); Faker.fakeSafari(); } }, { key: '_isVideoReq', value: function _isVideoReq(url) { return (/^https?:\/\/(?:\d+.?){4}\/videos\/v.*$/.test(url) ); } }, { key: 'mockForBestDefintion', value: function mockForBestDefintion() { var _this12 = this; // apply shims if (Detector.isFirefox()) { var fetch = unsafeWindow.fetch.bind(unsafeWindow); unsafeWindow.fetch = function (url, opts) { if (_this12._isVideoReq(url)) { Logger.log('fetching stream ' + url); return fetchStream(url, opts); // xhr with moz-chunked-arraybuffer } else { return fetch(url, opts); } }; } else if (Detector.isEdge()) { // export to the global window object unsafeWindow.RTCIceCandidate = window.RTCIceCandidate; unsafeWindow.RTCPeerConnection = window.RTCPeerConnection; unsafeWindow.RTCSessionDescription = window.RTCSessionDescription; } // auto fall-back if (Detector.isSupportVms()) { if (!Detector.isChrome()) this.mockToUseVms(); // vms, 1080p or higher } else if (Detector.isSupportM3u8()) { this.mockToUseM3u8(); // tmts m3u8 } else { // by default, tmts mp4 ... } } }, { key: '_isAdReq', value: function _isAdReq(url) { var AD_URL = 'http://t7z.cupid.iqiyi.com/show2'; return url.indexOf(AD_URL) === 0; } }, { key: 'mockAd', value: function mockAd() { var _this13 = this; Hooker.hookJqueryAjax(function (url, options) { if (_this13._isAdReq(url)) { var res = Faker.fakeAdRes(); (options.complete || options.success)({ responseJSON: res }, 'success'); Logger.log('mocked ad request ' + url); return true; } }); } }, { key: '_isCheckVipReq', value: function _isCheckVipReq(url) { var CHECK_VIP_URL = 'https://cmonitor.iqiyi.com/apis/user/check_vip.action'; return url === CHECK_VIP_URL; } }, { key: '_isLogin', value: function _isLogin() { return !!Cookies.get('P00001'); } }, { key: 'mockVip', value: function mockVip() { var _this14 = this; if (!this._isLogin()) Faker.fakePassportCookie(); Hooker.hookHttpJsonp(function (options) { var url = options.url; if (_this14._isCheckVipReq(url)) { var res = Faker.fakeVipRes(options.params.authcookie); options.success(res); Logger.log('mocked check vip request ' + url); return true; } }); } }, { key: 'mockLogo', value: function mockLogo() { Hooker.hookLogo(function (exports) { return exports.prototype.showLogo = function () {}; }); } }, { key: 'mockCheckPlugin', value: function mockCheckPlugin() { Hooker.hookSkinBase(function (exports) { exports.prototype._checkPlugin = function () {}; }); } }]); return Mocker; }(); var Patcher = function () { function Patcher() { _classCallCheck(this, Patcher); } _createClass(Patcher, null, [{ key: '_patchWebFullScreen', value: function _patchWebFullScreen() { Hooker.hookWebFullScreenInit(function (that, wrapper, btn) { btn.on('toggle', that.toggle.bind(that)); }); } }, { key: '_patchInitFullScreen', value: function _patchInitFullScreen() { this._patchWebFullScreen(); Hooker.hookInitFullScreen(function (that) { that.core.on('togglefullscreen', function () { that._fullscreenBtn.fire('click', { data: null }); }); that.core.on('togglewebfullscreen', function () { that._webfullscreenBtn.fire('toggle', { data: null }); }); }); } }, { key: '_patchPluginControls', value: function _patchPluginControls() { Hooker.hookPluginControlsInit(function (that) { that.core.on('showtip', function (event) { that.setcontroltip.apply(that, [{ str: event.data, x: that._process.offset().left, y: 3, cut: true, timeout: true }]); if (that.$plugin.hasClass('process_hidden')) { that._controltips.css('top', '-25px'); } else if (that.$plugin.hasClass('bottom-hide')) { that._controltips.css('top', '-38px'); } }); }); } }, { key: '_obtainFlvInfo', value: function _obtainFlvInfo() { var _this15 = this; Hooker.hookParseData(function (that) { return _this15._flvInfo = that.flvInfo; }); } }, { key: '_patchCore', value: function _patchCore() { var self = this; this._patchPluginControls(); this._patchInitFullScreen(); this._obtainFlvInfo(); Hooker.hookCore(function (exports) { exports.prototype._showTip = function (msg) { this.fire({ type: 'showtip', data: msg }); }; exports.prototype.getFPS = function () { if (self._flvInfo) { return self._flvInfo.videoConfigTag.sps.frame_rate.fps; } else { return 25; // f4v极速以上,动画23.976、电影24、电视剧25。 } }; exports.prototype.previousFrame = function () { var video = this.video(); var seekTime = Math.max(0, Math.min(this.getDuration(), video.currentTime - 1 / this.getFPS())); video.currentTime = seekTime; this._showTip('上一帧'); }; exports.prototype.nextFrame = function () { var video = this.video(); var seekTime = Math.max(0, Math.min(this.getDuration(), video.currentTime + 1 / this.getFPS())); video.currentTime = seekTime; this._showTip('下一帧'); }; exports.prototype.stepSeek = function (stepTime) { var seekTime = Math.max(0, Math.min(this.getDuration(), this.getCurrenttime() + stepTime)); 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); this.seek(seekTime, true); }; exports.prototype.rangeSeek = function (range) { var duration = this.getDuration(); var seekTime = Math.max(0, Math.min(duration, duration * range)); this.seek(seekTime, true); this._showTip('定位:' + (range * 100).toFixed(0) + '%'); }; exports.prototype.toggleMute = function () { if (this.getMuted()) { this.setMuted(false); this._showTip('取消静音'); } else { this.setMuted(true); this._showTip('静音'); } }; exports.prototype.adjustVolume = function (value) { var volume = this.getVolume() + value; volume = Math.max(0, Math.min(1, volume.toFixed(2))); this.setVolume(volume); this.fire({ type: 'keyvolumechange' }); }; exports.prototype.adjustPlaybackRate = function (value) { var video = this.video(); var playbackRate = Math.max(0.2, Math.min(5, video.playbackRate + value)); video.playbackRate = playbackRate; this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + playbackRate.toFixed(1).replace(/\.0+$/, '')); }; exports.prototype.resetPlaybackRate = function () { var video = this.video(); video.playbackRate = 1; this._showTip('恢复播放速率'); }; exports.prototype.hasPreVideo = function () { return this._getVideoIndexInList(this._movieinfo.tvid) > 0 || this._getVideoIndexInList(this._movieinfo.oldTvid) > 0; }; exports.prototype.playNext = function () { if (this.hasNextVideo()) { this._showTip('播放下一集'); this.switchNextVideo(); } else { this._showTip('没有下一集哦'); } }; exports.prototype.playPre = function () { if (this.hasPreVideo()) { this._showTip('播放上一集'); this.switchPreVideo(); } else { this._showTip('没有上一集哦'); } }; }); } }, { key: '_patchKeyShortcuts', value: function _patchKeyShortcuts() { Hooker.hookPluginHotKeys(function (exports) { exports.prototype.init = function () { document.addEventListener('keydown', this._keydown.bind(this)); }; exports.prototype._isValidTarget = function (target) { return target.nodeName === 'BODY' || target.nodeName == 'VIDEO' || target.classList.contains('pw-video'); // 全局 // return target.nodeName === 'VIDEO' || target.classList.contains('pw-video'); // 非全局 }; exports.prototype._keydown = function (event) { if (!this._isValidTarget(event.target)) return; switch (event.keyCode) { case 32: // Spacebar if (!event.ctrlKey && !event.shiftKey && !event.altKey) { if (this.core.isPaused()) { this.core.play(true); this.core._showTip('播放'); } else { this.core.pause(true); this.core._showTip('暂停'); } } 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.core.stepSeek(stepTime); break; } case 38: // ↑ Arrow Up case 40: // ↓ Arrow Down if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.adjustVolume(38 === event.keyCode ? 0.05 : -0.05); } else { return; } break; case 77: // M if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.toggleMute(); } else { return; } break; case 13: // Enter if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.fire({ type: 'togglefullscreen' }); } else if (event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.fire({ type: 'togglewebfullscreen' }); } else { return; } break; case 67: // C case 88: // X if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.adjustPlaybackRate(67 === event.keyCode ? 0.1 : -0.1); } else { return; } break; case 90: // Z if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.resetPlaybackRate(); } else { return; } break; case 68: // D case 70: // F if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.pause(true); if (event.keyCode === 68) { this.core.previousFrame(); } else { this.core.nextFrame(); } } else { return; } break; case 80: // P case 78: // N if (!event.ctrlKey && event.shiftKey && !event.altKey) { if (event.keyCode === 78) { this.core.playNext(); } else { this.core.playPre(); } } else { return; } break; default: if (event.keyCode >= 48 && event.keyCode <= 57) { // 0 ~ 9 if (!event.ctrlKey && !event.shiftKey && !event.altKey) { this.core.rangeSeek((event.keyCode - 48) * 0.1); } else { return; } } else { return; } } event.preventDefault(); event.stopPropagation(); }; Logger.log('添加键盘快捷键'); }); } }, { key: '_patchMouseShortcuts', value: function _patchMouseShortcuts() { Hooker.hookPluginControlsInit(function (that) { document.addEventListener('wheel', function (event) { if (!Detector.isFullScreen()) return; var delta = event.wheelDelta || event.detail || event.deltaY && -event.deltaY; that.core.adjustVolume(delta > 0 ? 0.05 : -0.05); }); Logger.log('添加鼠标快捷键'); }); } }, { key: 'patchShortcuts', value: function patchShortcuts() { this._patchCore(); this._patchKeyShortcuts(); this._patchMouseShortcuts(); } }]); return Patcher; }(); var Switcher = function () { function Switcher() { _classCallCheck(this, Switcher); } _createClass(Switcher, null, [{ key: 'switchTo', value: function switchTo(toType) { Logger.log('switching to ' + toType + ' ...'); GM_setValue('player_forcedType', toType); document.location.reload(); } }]); return Switcher; }(); var Finder = function () { function Finder() { _classCallCheck(this, Finder); } _createClass(Finder, null, [{ key: 'findVid', value: function findVid(text) { var result = /vid=([\da-z]+)/i.exec(text); return result ? result[1] : null; } }, { key: 'findTvid', value: function findTvid(text) { var result = /tvid=(\d+)/i.exec(text); return result ? result[1] : null; } }, { key: 'findEmbedNodes', value: function findEmbedNodes() { var nodes = document.querySelectorAll('object, embed'); return nodes.length > 0 ? nodes : null; } }]); return Finder; }(); function getVideoUrl(tvid, vid) { return new Promise(function (resolve, reject) { GM_xmlhttpRequest({ url: 'http://cache.video.qiyi.com/jp/vi/' + tvid + '/' + vid + '/?callback=callback', method: 'GET', timeout: 8e3, onload: function onload(details) { try { var json = JSON.parse(/callback\s*\(\s*(\{.*\})\s*\)/.exec(details.responseText)[1]); resolve(json.vu); } catch (err) { reject(err); } }, onerror: reject, onabort: reject, ontimeout: reject }); }); } function embedSrc(targetNode, _ref2) { var tvid = _ref2.tvid, vid = _ref2.vid; targetNode.innerHTML = '
\u6B63\u5728\u83B7\u53D6\u89C6\u9891\u6E90...
'; getVideoUrl(tvid, vid).then(function (url) { Logger.log('origin url: %s', url); targetNode.innerHTML = ''; }).catch(function (err) { targetNode.innerHTML = '

\u83B7\u53D6\u89C6\u9891\u6E90\u51FA\u9519\uFF01

' + err.message + '

'; }); } function replaceFlash() { var observer = new MutationObserver(function (records, self) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = records[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var record = _step.value; if (record.type !== 'childList' || !record.addedNodes) continue; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = record.addedNodes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var node = _step2.value; if (node.nodeName !== 'OBJECT' && node.nodeName !== 'EMBED') continue; Logger.log('finded node', node); var text = node.outerHTML; var vid = Finder.findVid(text); var tvid = Finder.findTvid(text); if (tvid && vid) { Logger.log('finded tvid: %s, vid: %s', tvid, vid); embedSrc(node.parentNode, { tvid: tvid, vid: vid }); self.disconnect(); Logger.log('stoped observation'); } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } }); observer.observe(document.body || document.documentElement, { subtree: true, childList: true }); Logger.log('started observation'); } function adaptIframe() { var style = '\n body[class|="qypage"] {\n overflow: hidden !important;\n background: #000 !important;\n visibility: hidden;\n }\n\n .mod-func {\n display: none !important;\n }\n\n .' + GM_info.script.name + '.info {\n width: 20em;\n height: 5em;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n margin: auto;\n text-align: center;\n line-height: 5em;\n font-size: 1em;\n color: #ccc;\n }\n\n .' + GM_info.script.name + '.error {\n height: 3em;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n margin: auto;\n text-align: center;\n font-size: 1em;\n color: #c00;\n }\n '; GM_addStyle(style); Hooker.hookWebFullScreen(function (exports) { var init = exports.__proto__.init; exports.__proto__.init = function (wrapper, btn) { init.apply(this, [wrapper, btn]); this.enter(); btn[0].style.display = 'none'; document.body.style.visibility = 'visible'; }; exports.__proto__.exit = function () {}; }); Hooker.hookCore(function (exports) { exports.prototype.hasNextVideo = function () { return null; }; }); } function forceHtml5() { Logger.log('setting player_forcedType cookie as ' + PLAYER_TYPE.Html5VOD); Cookies.set('player_forcedType', PLAYER_TYPE.Html5VOD, { domain: '.iqiyi.com' }); } function forceFlash() { Logger.log('setting player_forcedType cookie as ' + PLAYER_TYPE.FlashVOD); Cookies.set('player_forcedType', PLAYER_TYPE.FlashVOD, { domain: '.iqiyi.com' }); } function clean() { Cookies.remove('player_forcedType', { domain: '.iqiyi.com' }); if (Cookies.get('P00001') === 'faked_passport') Cookies.remove('P00001', { domain: '.iqiyi.com' }); Logger.log('removed cookies.'); } function registerMenu() { var MENU_NAME = { HTML5: 'HTML5播放器', FLASH: 'Flash播放器' }; var currType = GM_getValue('player_forcedType', PLAYER_TYPE.Html5VOD); // 默认为Html5播放器,免去切换。 var _ref3 = currType === PLAYER_TYPE.Html5VOD ? [PLAYER_TYPE.FlashVOD, MENU_NAME.FLASH] : [PLAYER_TYPE.Html5VOD, MENU_NAME.HTML5], _ref4 = _slicedToArray(_ref3, 2), toType = _ref4[0], name = _ref4[1]; GM_registerMenuCommand(name, function () { return Switcher.switchTo(toType); }, null); Logger.log('registered menu.'); } //============================================================================= registerMenu(); var currType = GM_getValue('player_forcedType', PLAYER_TYPE.Html5VOD); if (currType === PLAYER_TYPE.Html5VOD) { if (!Detector.isSupportHtml5()) { alert('╮(╯▽╰)╭ 你的浏览器播放不了html5视频~~~~'); return; } forceHtml5(); Mocker.mock(); Patcher.patchShortcuts(); if (Detector.isInnerFrame()) adaptIframe(); if (Detector.isOutsite()) { if (!Detector.hasFlashPlugin()) Faker.fakeFlashPlugin(); replaceFlash(); } } else { forceFlash(); } window.addEventListener('unload', function () { return clean(); }); })();