ykh5p

改善优酷官方html5播放器播放体验

当前为 2017-09-20 提交的版本,查看 最新版本

  1. 'use strict';
  2.  
  3. 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"); } }; }();
  4.  
  5. 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; }; }();
  6.  
  7. 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; }
  8.  
  9. 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; }
  10.  
  11. 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); } }
  12.  
  13. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  14.  
  15. // ==UserScript==
  16. // @name ykh5p
  17. // @namespace https://github.com/gooyie/ykh5p
  18. // @homepageURL https://github.com/gooyie/ykh5p
  19. // @supportURL https://github.com/gooyie/ykh5p/issues
  20. // @version 0.10.1
  21. // @description 改善优酷官方html5播放器播放体验
  22. // @author gooyie
  23. // @license MIT License
  24. //
  25. // @include *://v.youku.com/*
  26. // @grant GM_info
  27. // @grant GM_addStyle
  28. // @grant unsafeWindow
  29. // @run-at document-start
  30. // ==/UserScript==
  31.  
  32. (function () {
  33. 'use strict';
  34.  
  35. /* eslint-disable no-console */
  36.  
  37. var Logger = function () {
  38. function Logger() {
  39. _classCallCheck(this, Logger);
  40. }
  41.  
  42. _createClass(Logger, null, [{
  43. key: 'log',
  44. value: function log() {
  45. var _console;
  46.  
  47. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  48. args[_key] = arguments[_key];
  49. }
  50.  
  51. (_console = console).log.apply(_console, ['%c' + this.tag + '%c' + args.shift(), 'color: #fff; background: #2FB3FF', ''].concat(args));
  52. }
  53. }, {
  54. key: 'info',
  55. value: function info() {
  56. var _console2;
  57.  
  58. for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  59. args[_key2] = arguments[_key2];
  60. }
  61.  
  62. (_console2 = console).info.apply(_console2, [this.tag + args.shift()].concat(args));
  63. }
  64. }, {
  65. key: 'debug',
  66. value: function debug() {
  67. var _console3;
  68.  
  69. for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
  70. args[_key3] = arguments[_key3];
  71. }
  72.  
  73. (_console3 = console).debug.apply(_console3, [this.tag + args.shift()].concat(args));
  74. }
  75. }, {
  76. key: 'warn',
  77. value: function warn() {
  78. var _console4;
  79.  
  80. for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
  81. args[_key4] = arguments[_key4];
  82. }
  83.  
  84. (_console4 = console).warn.apply(_console4, [this.tag + args.shift()].concat(args));
  85. }
  86. }, {
  87. key: 'error',
  88. value: function error() {
  89. var _console5;
  90.  
  91. for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
  92. args[_key5] = arguments[_key5];
  93. }
  94.  
  95. (_console5 = console).error.apply(_console5, [this.tag + args.shift()].concat(args));
  96. }
  97. }, {
  98. key: 'tag',
  99. get: function get() {
  100. return '[' + GM_info.script.name + ']';
  101. }
  102. }]);
  103.  
  104. return Logger;
  105. }();
  106. /* eslint-enable no-console */
  107.  
  108. var Hooker = function () {
  109. function Hooker() {
  110. _classCallCheck(this, Hooker);
  111. }
  112.  
  113. _createClass(Hooker, null, [{
  114. key: '_hookCall',
  115. value: function _hookCall(cb) {
  116. var call = Function.prototype.call;
  117. Function.prototype.call = function () {
  118. for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
  119. args[_key6] = arguments[_key6];
  120. }
  121.  
  122. var ret = call.apply(this, args);
  123. try {
  124. if (args && cb(args)) {
  125. Function.prototype.call = call;
  126. cb = function cb() {};
  127. Logger.log('restored call');
  128. }
  129. } catch (err) {
  130. Logger.error(err.stack);
  131. }
  132. return ret;
  133. };
  134. this._hookCall = null;
  135. }
  136. }, {
  137. key: '_isEsModule',
  138. value: function _isEsModule(obj) {
  139. return obj.__esModule;
  140. }
  141. }, {
  142. key: '_isFuction',
  143. value: function _isFuction(arg) {
  144. return 'function' === typeof arg;
  145. }
  146. }, {
  147. key: '_isModuleCall',
  148. value: function _isModuleCall(args) {
  149. // module.exports, module, module.exports, require
  150. return args.length === 4 && args[1] && Object.getPrototypeOf(args[1]) === Object.prototype && args[1].hasOwnProperty('exports');
  151. }
  152. }, {
  153. key: '_hookModuleCall',
  154. value: function _hookModuleCall(cb, pred) {
  155. var _this = this;
  156.  
  157. var callbacksMap = new Map([[pred, [cb]]]);
  158. this._hookCall(function (args) {
  159. if (!_this._isModuleCall(args)) return;
  160. var exports = args[1].exports;
  161. var _iteratorNormalCompletion = true;
  162. var _didIteratorError = false;
  163. var _iteratorError = undefined;
  164.  
  165. try {
  166. for (var _iterator = callbacksMap[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  167. var _step$value = _slicedToArray(_step.value, 2),
  168. _pred = _step$value[0],
  169. callbacks = _step$value[1];
  170.  
  171. if (!_pred.apply(_this, [exports])) continue;
  172. callbacks.forEach(function (cb) {
  173. return cb(exports, args);
  174. });
  175. callbacksMap.delete(_pred);
  176. !callbacksMap.size && (_this._hookModuleCall = null);
  177. break;
  178. }
  179. } catch (err) {
  180. _didIteratorError = true;
  181. _iteratorError = err;
  182. } finally {
  183. try {
  184. if (!_iteratorNormalCompletion && _iterator.return) {
  185. _iterator.return();
  186. }
  187. } finally {
  188. if (_didIteratorError) {
  189. throw _iteratorError;
  190. }
  191. }
  192. }
  193.  
  194. return !callbacksMap.size;
  195. });
  196.  
  197. this._hookModuleCall = function (cb, pred) {
  198. if (callbacksMap.has(pred)) {
  199. callbacksMap.get(pred).push(cb);
  200. } else {
  201. callbacksMap.set(pred, [cb]);
  202. }
  203. };
  204. }
  205. }, {
  206. key: '_isUpsModuleCall',
  207. value: function _isUpsModuleCall(exports) {
  208. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('getServieceUrl') && /\.id\s*=\s*"ups"/.test(exports.default.toString());
  209. }
  210. }, {
  211. key: 'hookUps',
  212. value: function hookUps(cb) {
  213. this._hookModuleCall(cb, this._isUpsModuleCall);
  214. }
  215. }, {
  216. key: 'hookUpsOnComplete',
  217. value: function hookUpsOnComplete(cb) {
  218. this.hookUps(function (exports) {
  219. var onComplete = exports.default.prototype.onComplete;
  220. exports.default.prototype.onComplete = function (res) {
  221. cb(res);
  222. onComplete.apply(this, [res]);
  223. };
  224. });
  225. }
  226. }, {
  227. key: '_isLogoModuleCall',
  228. value: function _isLogoModuleCall(exports) {
  229. 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());
  230. }
  231. }, {
  232. key: 'hookLogo',
  233. value: function hookLogo(cb) {
  234. this._hookModuleCall(cb, this._isLogoModuleCall);
  235. }
  236. }, {
  237. key: '_isQualityIconComponentModuleCall',
  238. value: function _isQualityIconComponentModuleCall(exports) {
  239. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('renderQuality');
  240. }
  241. }, {
  242. key: 'hookQualityIcon',
  243. value: function hookQualityIcon(cb) {
  244. this._hookModuleCall(cb, this._isQualityIconComponentModuleCall);
  245. }
  246. }, {
  247. key: 'hookRenderQuality',
  248. value: function hookRenderQuality(cb) {
  249. Hooker.hookQualityIcon(function (exports) {
  250. var renderQuality = exports.default.prototype.renderQuality;
  251. exports.default.prototype.renderQuality = function (langCode) {
  252. cb(langCode, this);
  253. renderQuality.apply(this, [langCode]);
  254. };
  255. });
  256. }
  257. }, {
  258. key: 'hookSetQuality',
  259. value: function hookSetQuality(cb) {
  260. Hooker.hookQualityIcon(function (exports) {
  261. var setQuality = exports.default.prototype.setQuality;
  262. exports.default.prototype.setQuality = function () {
  263. for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
  264. args[_key7] = arguments[_key7];
  265. }
  266.  
  267. // quality, innerText
  268. cb(args, this);
  269. setQuality.apply(this, args);
  270. };
  271. });
  272. }
  273. }, {
  274. key: '_isManageModuleCall',
  275. value: function _isManageModuleCall(exports) {
  276. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_resetPlayer');
  277. }
  278. }, {
  279. key: 'hookManage',
  280. value: function hookManage(cb) {
  281. this._hookModuleCall(cb, this._isManageModuleCall);
  282. }
  283. }, {
  284. key: 'hookInitPlayerEvent',
  285. value: function hookInitPlayerEvent(cb) {
  286. Hooker.hookManage(function (exports) {
  287. var _initPlayerEvent = exports.default.prototype._initPlayerEvent;
  288. exports.default.prototype._initPlayerEvent = function () {
  289. cb(this);
  290. _initPlayerEvent.apply(this);
  291. };
  292. });
  293. }
  294. }, {
  295. key: 'hookResetPlayerAfter',
  296. value: function hookResetPlayerAfter(cb) {
  297. Hooker.hookManage(function (exports) {
  298. var _resetPlayer = exports.default.prototype._resetPlayer;
  299. exports.default.prototype._resetPlayer = function () {
  300. try {
  301. _resetPlayer.apply(this);
  302. } catch (err) {
  303. // 忽略 ykSDK.destroyAd 异常
  304. if (!err.stack.includes('destroyAd')) throw err;
  305. }
  306. cb(this);
  307. };
  308. });
  309. }
  310. }, {
  311. key: '_isKeyShortcutsModuleCall',
  312. value: function _isKeyShortcutsModuleCall(exports) {
  313. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('registerEvents');
  314. }
  315. }, {
  316. key: 'hookKeyShortcuts',
  317. value: function hookKeyShortcuts(cb) {
  318. this._hookModuleCall(cb, this._isKeyShortcutsModuleCall);
  319. }
  320. }, {
  321. key: '_isTipsModuleCall',
  322. value: function _isTipsModuleCall(exports) {
  323. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showHintTips');
  324. }
  325. }, {
  326. key: 'hookTips',
  327. value: function hookTips(cb) {
  328. this._hookModuleCall(cb, this._isTipsModuleCall);
  329. }
  330. }, {
  331. key: '_isAdServiceModuleCall',
  332. value: function _isAdServiceModuleCall(exports) {
  333. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('requestAdData');
  334. }
  335. }, {
  336. key: 'hookAdService',
  337. value: function hookAdService(cb) {
  338. this._hookModuleCall(cb, this._isAdServiceModuleCall);
  339. }
  340. }, {
  341. key: '_isTopAreaModuleCall',
  342. value: function _isTopAreaModuleCall(exports) {
  343. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_timerHandler');
  344. }
  345. }, {
  346. key: 'hookTopArea',
  347. value: function hookTopArea(cb) {
  348. this._hookModuleCall(cb, this._isTopAreaModuleCall);
  349. }
  350. }, {
  351. key: 'hookTopAreaAddEvent',
  352. value: function hookTopAreaAddEvent(cb) {
  353. Hooker.hookTopArea(function (exports) {
  354. var _addEvent = exports.default.prototype._addEvent;
  355. exports.default.prototype._addEvent = function () {
  356. cb(this);
  357. _addEvent.apply(this);
  358. };
  359. });
  360. }
  361. }, {
  362. key: '_isPreviewLayerModuleCall',
  363. value: function _isPreviewLayerModuleCall(exports) {
  364. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setPreviewShow');
  365. }
  366. }, {
  367. key: 'hookPreviewLayer',
  368. value: function hookPreviewLayer(cb) {
  369. this._hookModuleCall(cb, this._isPreviewLayerModuleCall);
  370. }
  371. }, {
  372. key: 'hookPreviewLayerBind',
  373. value: function hookPreviewLayerBind(cb) {
  374. Hooker.hookPreviewLayer(function (exports) {
  375. var bind = exports.default.prototype.bind;
  376. exports.default.prototype.bind = function () {
  377. cb(this);
  378. bind.apply(this);
  379. };
  380. });
  381. }
  382. }, {
  383. key: '_isSettingSeriesComponentModuleCall',
  384. value: function _isSettingSeriesComponentModuleCall(exports) {
  385. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_addEvent') && exports.default.prototype._addEvent.toString().includes('seriesliseLayer');
  386. }
  387. }, {
  388. key: 'hookSettingSeries',
  389. value: function hookSettingSeries(cb) {
  390. this._hookModuleCall(cb, this._isSettingSeriesComponentModuleCall);
  391. }
  392. }, {
  393. key: '_isGlobalModuleCall',
  394. value: function _isGlobalModuleCall(exports) {
  395. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('resetConfig');
  396. }
  397. }, {
  398. key: 'hookGlobal',
  399. value: function hookGlobal(cb) {
  400. this._hookModuleCall(cb, this._isGlobalModuleCall);
  401. }
  402. }, {
  403. key: 'hookGlobalConstructorAfter',
  404. value: function hookGlobalConstructorAfter(cb) {
  405. Hooker.hookGlobal(function (exports) {
  406. var constructor = exports.default;
  407. exports.default = function () {
  408. for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
  409. args[_key8] = arguments[_key8];
  410. }
  411.  
  412. constructor.apply(this, args);
  413. cb(this);
  414. };
  415. exports.default.prototype = constructor.prototype;
  416. });
  417. }
  418. }, {
  419. key: 'hookGlobalInit',
  420. value: function hookGlobalInit(cb) {
  421. Hooker.hookGlobal(function (exports) {
  422. var init = exports.default.prototype.init;
  423. exports.default.prototype.init = function (config) {
  424. cb(config, this);
  425. init.apply(this, [config]);
  426. };
  427. });
  428. }
  429. }, {
  430. key: 'hookGlobalDeal',
  431. value: function hookGlobalDeal(cb) {
  432. Hooker.hookGlobal(function (exports) {
  433. var deal = exports.default.prototype.deal;
  434. exports.default.prototype.deal = function () {
  435. cb(this);
  436. deal.apply(this);
  437. };
  438. });
  439. }
  440. }, {
  441. key: 'hookGlobalResetAfter',
  442. value: function hookGlobalResetAfter(cb) {
  443. Hooker.hookGlobal(function (exports) {
  444. var reset = exports.default.prototype.reset;
  445. exports.default.prototype.reset = function () {
  446. reset.apply(this);
  447. cb(this);
  448. };
  449. });
  450. }
  451. }, {
  452. key: 'hookAdaptQualityAfter',
  453. value: function hookAdaptQualityAfter(cb) {
  454. Hooker.hookGlobal(function (exports) {
  455. var adaptQuality = exports.default.prototype.adaptQuality;
  456. exports.default.prototype.adaptQuality = function (lang) {
  457. adaptQuality.apply(this, [lang]);
  458. cb(this);
  459. };
  460. });
  461. }
  462. }, {
  463. key: '_extractArgsName',
  464. value: function _extractArgsName(code) {
  465. return code.slice(code.indexOf('(') + 1, code.indexOf(')')).split(/\s*,\s*/);
  466. }
  467. }, {
  468. key: '_extractFunctionBody',
  469. value: function _extractFunctionBody(code) {
  470. return code.slice(code.indexOf('{') + 1, code.lastIndexOf('}'));
  471. }
  472. }, {
  473. key: '_isBaseModuleCall',
  474. value: function _isBaseModuleCall(exports) {
  475. return exports.SingleVideoControl && exports.MultiVideoControl;
  476. }
  477. }, {
  478. key: 'hookBase',
  479. value: function hookBase(cb, mode) {
  480. var _this2 = this;
  481.  
  482. var callbacks = [];
  483. var codeCallbacks = [];
  484. (mode === 'code' ? codeCallbacks : callbacks).push(cb);
  485.  
  486. this._hookModuleCall(function (exports, args) {
  487. if (codeCallbacks.length > 0) {
  488. var code = args[3].m[args[1].i].toString();
  489. code = codeCallbacks.reduce(function (c, cb) {
  490. return cb(c);
  491. }, code);
  492. var fn = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(_this2._extractArgsName(code)), [_this2._extractFunctionBody(code)])))();
  493. fn.apply(args[0], args.slice(1));
  494. }
  495. callbacks.forEach(function (cb) {
  496. return cb(args[1].exports);
  497. });
  498. _this2.hookBase = null;
  499. }, this._isBaseModuleCall);
  500.  
  501. this.hookBase = function (cb, mode) {
  502. return (mode === 'code' ? codeCallbacks : callbacks).push(cb);
  503. };
  504. }
  505. }, {
  506. key: 'hookOz',
  507. value: function hookOz(cb) {
  508. var callbacks = [cb];
  509. var window = unsafeWindow;
  510. var oz = window.oz; // oz 可能先于脚本执行
  511. Object.defineProperty(window, 'oz', {
  512. get: function get() {
  513. return oz;
  514. },
  515. set: function set(value) {
  516. oz = value;
  517. try {
  518. callbacks.forEach(function (cb) {
  519. return cb(oz);
  520. });
  521. } catch (err) {
  522. Logger.error(err.stack);
  523. }
  524. }
  525. });
  526. if (oz) window.oz = oz; // oz 先于脚本执行
  527.  
  528. this.hookOz = function (cb) {
  529. return callbacks.push(cb);
  530. };
  531. }
  532. }, {
  533. key: 'hookDefine',
  534. value: function hookDefine(name, cb) {
  535. var _this3 = this;
  536.  
  537. var callbacksMap = new Map([[name, [cb]]]);
  538. this.hookOz(function (oz) {
  539. var self = _this3;
  540. var define = oz.define;
  541. oz.define = function (name, deps, block) {
  542. if (callbacksMap.has(name)) {
  543. var code = block.toString();
  544. code = callbacksMap.get(name).reduce(function (c, cb) {
  545. return cb(c);
  546. }, code);
  547. block = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(self._extractArgsName(code)), [self._extractFunctionBody(code)])))();
  548. }
  549. define(name, deps, block);
  550. };
  551. });
  552.  
  553. this.hookDefine = function (name, cb) {
  554. if (callbacksMap.has(name)) {
  555. callbacksMap.get(name).push(cb);
  556. } else {
  557. callbacksMap.set(name, [cb]);
  558. }
  559. };
  560. }
  561. }]);
  562.  
  563. return Hooker;
  564. }();
  565.  
  566. var Patch = function () {
  567. function Patch() {
  568. _classCallCheck(this, Patch);
  569.  
  570. this._installed = false;
  571. }
  572.  
  573. _createClass(Patch, [{
  574. key: 'install',
  575. value: function install() {
  576. if (!this._installed) {
  577. this._installed = true;
  578. this._apply();
  579. }
  580. }
  581. }, {
  582. key: '_apply',
  583. value: function _apply() {}
  584. }]);
  585.  
  586. return Patch;
  587. }();
  588.  
  589. var AdBlockPatch = function (_Patch) {
  590. _inherits(AdBlockPatch, _Patch);
  591.  
  592. function AdBlockPatch() {
  593. _classCallCheck(this, AdBlockPatch);
  594.  
  595. return _possibleConstructorReturn(this, (AdBlockPatch.__proto__ || Object.getPrototypeOf(AdBlockPatch)).call(this));
  596. }
  597.  
  598. _createClass(AdBlockPatch, [{
  599. key: '_apply',
  600. value: function _apply() {
  601. Hooker.hookAdService(function (exports) {
  602. exports.default.prototype.requestAdData = function (arg) {
  603. var _this5 = this;
  604.  
  605. setTimeout(function () {
  606. _this5.fail(arg, { code: '404', message: 'error' });
  607. }, 0);
  608. };
  609. });
  610. }
  611. }]);
  612.  
  613. return AdBlockPatch;
  614. }(Patch);
  615.  
  616. var WatermarksPatch = function (_Patch2) {
  617. _inherits(WatermarksPatch, _Patch2);
  618.  
  619. function WatermarksPatch() {
  620. _classCallCheck(this, WatermarksPatch);
  621.  
  622. return _possibleConstructorReturn(this, (WatermarksPatch.__proto__ || Object.getPrototypeOf(WatermarksPatch)).call(this));
  623. }
  624.  
  625. _createClass(WatermarksPatch, [{
  626. key: '_apply',
  627. value: function _apply() {
  628. Hooker.hookLogo(function (exports) {
  629. exports.default.prototype.reset = function () {};
  630. });
  631. }
  632. }]);
  633.  
  634. return WatermarksPatch;
  635. }(Patch);
  636.  
  637. var VipPatch = function (_Patch3) {
  638. _inherits(VipPatch, _Patch3);
  639.  
  640. function VipPatch() {
  641. _classCallCheck(this, VipPatch);
  642.  
  643. return _possibleConstructorReturn(this, (VipPatch.__proto__ || Object.getPrototypeOf(VipPatch)).call(this));
  644. }
  645.  
  646. _createClass(VipPatch, [{
  647. key: '_apply',
  648. value: function _apply() {
  649. Hooker.hookUpsOnComplete(function (res) {
  650. var data = res.data;
  651. data.user = Object.assign(data.user || {}, { vip: true });
  652. data.vip = Object.assign(data.vip || {}, { hd3: true });
  653. });
  654. }
  655. }]);
  656.  
  657. return VipPatch;
  658. }(Patch);
  659.  
  660. var QualityPatch = function (_Patch4) {
  661. _inherits(QualityPatch, _Patch4);
  662.  
  663. function QualityPatch() {
  664. _classCallCheck(this, QualityPatch);
  665.  
  666. return _possibleConstructorReturn(this, (QualityPatch.__proto__ || Object.getPrototypeOf(QualityPatch)).call(this));
  667. }
  668.  
  669. _createClass(QualityPatch, [{
  670. key: '_apply',
  671. value: function _apply() {
  672. this._savePreferQuality();
  673. this._improveAdaptQuality();
  674. }
  675. }, {
  676. key: '_savePreferQuality',
  677. value: function _savePreferQuality() {
  678. // 选择的画质作为优先画质并保存至localStorage
  679. Hooker.hookSetQuality(function (_ref, that) {
  680. var _ref2 = _slicedToArray(_ref, 1),
  681. quality = _ref2[0];
  682.  
  683. return that.data.preferQuality = quality;
  684. });
  685. }
  686. }, {
  687. key: '_findBestQuality',
  688. value: function _findBestQuality(qualityList) {
  689. return ['1080p', '720p', '480p', '320p'].find(function (q) {
  690. return qualityList.some(function (v) {
  691. return v === q;
  692. });
  693. });
  694. }
  695. }, {
  696. key: '_improveAdaptQuality',
  697. value: function _improveAdaptQuality() {
  698. var _this9 = this;
  699.  
  700. Hooker.hookAdaptQualityAfter(function (that) {
  701. var cfg = that._config;
  702. if (cfg.quality !== cfg.preferQuality) {
  703. // 设置的优先画质在当前视频没有
  704. cfg.defaultQuality = cfg.quality = _this9._findBestQuality(that.qualityList) || cfg.quality;
  705. }
  706. });
  707. }
  708. }]);
  709.  
  710. return QualityPatch;
  711. }(Patch);
  712.  
  713. var SkipLocalPlayRecordPatch = function (_Patch5) {
  714. _inherits(SkipLocalPlayRecordPatch, _Patch5);
  715.  
  716. function SkipLocalPlayRecordPatch() {
  717. _classCallCheck(this, SkipLocalPlayRecordPatch);
  718.  
  719. return _possibleConstructorReturn(this, (SkipLocalPlayRecordPatch.__proto__ || Object.getPrototypeOf(SkipLocalPlayRecordPatch)).call(this));
  720. }
  721.  
  722. _createClass(SkipLocalPlayRecordPatch, [{
  723. key: '_apply',
  724. value: function _apply() {
  725. Hooker.hookManage(function (exports) {
  726. var skipLocalPlayRecord = exports.default.prototype.skipLocalPlayRecord;
  727. exports.default.prototype.skipLocalPlayRecord = function () {
  728. var cfg = this.global.config;
  729. var headPosition = cfg.headPosition;
  730. cfg.headPosition = cfg.playRecord;
  731. skipLocalPlayRecord.apply(this);
  732. cfg.headPosition = headPosition;
  733. };
  734. });
  735. }
  736. }]);
  737.  
  738. return SkipLocalPlayRecordPatch;
  739. }(Patch);
  740.  
  741. var DashboardPatch = function (_Patch6) {
  742. _inherits(DashboardPatch, _Patch6);
  743.  
  744. function DashboardPatch() {
  745. _classCallCheck(this, DashboardPatch);
  746.  
  747. return _possibleConstructorReturn(this, (DashboardPatch.__proto__ || Object.getPrototypeOf(DashboardPatch)).call(this));
  748. }
  749.  
  750. _createClass(DashboardPatch, [{
  751. key: '_apply',
  752. value: function _apply() {
  753. this._prepare();
  754. this._patch();
  755. }
  756. }, {
  757. key: '_prepare',
  758. value: function _prepare() {
  759. this._exposeDashboard();
  760. Hooker.hookPreviewLayerBind(function (that) {
  761. that._el.addEventListener('mouseover', function () {
  762. return that.emit('mouseoverpreview');
  763. });
  764. that._el.addEventListener('mouseleave', function () {
  765. return that.emit('mouseleavepreview');
  766. });
  767. });
  768. }
  769. }, {
  770. key: '_findVarName',
  771. value: function _findVarName(code) {
  772. return (/"dashboard"\s*,\s*(\w+)/.exec(code)[1]
  773. );
  774. }
  775. }, {
  776. key: '_exposeDashboard',
  777. value: function _exposeDashboard() {
  778. var _this12 = this;
  779.  
  780. Hooker.hookBase(function (code) {
  781. var varName = _this12._findVarName(code);
  782. return code.replace(/\.exports\s*=\s*(\w+)/, '$&;$1.__Dashboard=' + varName + ';');
  783. }, 'code');
  784. }
  785. }, {
  786. key: '_patch',
  787. value: function _patch() {
  788. Hooker.hookBase(function (exports) {
  789. var proto = exports.__Dashboard.prototype;
  790.  
  791. proto.bindAutoHide = function () {
  792. var _this13 = this;
  793.  
  794. this._args.show = 'function' === typeof this._args.show ? this._args.show : function () {};
  795. this._args.hide = 'function' === typeof this._args.hide ? this._args.show : function () {};
  796.  
  797. this._el.addEventListener('mouseover', function () {
  798. return _this13._mouseover = true;
  799. });
  800. this._el.addEventListener('mouseleave', function () {
  801. return _this13._mouseover = false;
  802. });
  803. this.on('mouseoverpreview', function () {
  804. return _this13._mouseoverpreview = true;
  805. });
  806. this.on('mouseleavepreview', function () {
  807. return _this13._mouseoverpreview = false;
  808. });
  809. this._video.on('play', function () {
  810. if (!_this13._mouseover && !_this13._mouseoverpreview) _this13._hideTimeout = setTimeout(_this13.hide.bind(_this13), _this13._args.autoHide);
  811. });
  812. this._video.on('pause', function () {
  813. _this13._hideTimeout && clearTimeout(_this13._hideTimeout);
  814. _this13.isShow() || _this13.show();
  815. });
  816. this._parent.addEventListener('mousemove', function () {
  817. _this13._hideTimeout && clearTimeout(_this13._hideTimeout);
  818. _this13.isShow() || _this13.show();
  819. if (!_this13._isPaused() && !_this13._mouseover && !_this13._mouseoverpreview) _this13._hideTimeout = setTimeout(_this13.hide.bind(_this13), _this13._args.autoHide);
  820. });
  821. this._parent.addEventListener('mouseleave', function () {
  822. _this13._hideTimeout && clearTimeout(_this13._hideTimeout);
  823. if (!_this13._isPaused()) _this13.hide();
  824. });
  825. };
  826.  
  827. proto._isPaused = function () {
  828. return this._video._videoCore.video.paused;
  829. };
  830.  
  831. proto.isShow = function () {
  832. return this._el.style.display !== 'none';
  833. };
  834.  
  835. proto.show = function () {
  836. this.emit('dashboardshow');
  837. this._parent.style.cursor = '';
  838. this._el.style.display = '';
  839. this._args.show();
  840. };
  841.  
  842. proto.hide = function () {
  843. this.emit('dashboardhide');
  844. this._parent.style.cursor = 'none'; // 隐藏鼠标
  845. this._el.style.display = 'none';
  846. this._args.show();
  847. };
  848. });
  849. }
  850. }]);
  851.  
  852. return DashboardPatch;
  853. }(Patch);
  854.  
  855. var TopAreaPatch = function (_Patch7) {
  856. _inherits(TopAreaPatch, _Patch7);
  857.  
  858. function TopAreaPatch() {
  859. _classCallCheck(this, TopAreaPatch);
  860.  
  861. return _possibleConstructorReturn(this, (TopAreaPatch.__proto__ || Object.getPrototypeOf(TopAreaPatch)).call(this));
  862. }
  863.  
  864. _createClass(TopAreaPatch, [{
  865. key: '_apply',
  866. value: function _apply() {
  867. Hooker.hookTopAreaAddEvent(function (that) {
  868. that.on('webfullscreen', function (isWebFullscreen) {
  869. isWebFullscreen ? that._showHideTop(true) : that._hideHideTop();
  870. });
  871. that.on('dashboardshow', function () {
  872. var playerState = that._video.global.playerState;
  873. if (playerState.fullscreen || playerState.webfullscreen) {
  874. that._showHideTop(true);
  875. }
  876. });
  877. that.on('dashboardhide', function () {
  878. var playerState = that._video.global.playerState;
  879. if (playerState.fullscreen || playerState.webfullscreen) {
  880. that._hideHideTop();
  881. }
  882. });
  883. });
  884. Hooker.hookResetPlayerAfter(function (that) {
  885. // 网页全屏播放上下集重置播放器后显示顶部控件
  886. if (!that.global.playerState.fullscreen) that._player.control.emit('webfullscreen', that.global.playerState.webfullscreen);
  887. });
  888. }
  889. }]);
  890.  
  891. return TopAreaPatch;
  892. }(Patch);
  893.  
  894. var SettingSeriesPatch = function (_Patch8) {
  895. _inherits(SettingSeriesPatch, _Patch8);
  896.  
  897. function SettingSeriesPatch() {
  898. _classCallCheck(this, SettingSeriesPatch);
  899.  
  900. return _possibleConstructorReturn(this, (SettingSeriesPatch.__proto__ || Object.getPrototypeOf(SettingSeriesPatch)).call(this));
  901. }
  902.  
  903. _createClass(SettingSeriesPatch, [{
  904. key: '_apply',
  905. value: function _apply() {
  906. Hooker.hookSettingSeries(function (exports) {
  907. // 网页全屏显示选集
  908. var _addEvent = exports.default.prototype._addEvent;
  909. exports.default.prototype._addEvent = function () {
  910. var _this16 = this;
  911.  
  912. _addEvent.apply(this);
  913. this.on('webfullscreen', function (isWebFullscreen) {
  914. if (isWebFullscreen) {
  915. if (_this16.seriesList.length > 1) _this16._el.style.display = 'inline-block';
  916. } else {
  917. _this16._el.style.display = 'none';
  918. _this16._el.classList.remove('cliced');
  919. _this16.emit('seriesliseLayer', false);
  920. }
  921. });
  922. };
  923. });
  924. }
  925. }]);
  926.  
  927. return SettingSeriesPatch;
  928. }(Patch);
  929.  
  930. var ContinuePlayPatch = function (_Patch9) {
  931. _inherits(ContinuePlayPatch, _Patch9);
  932.  
  933. function ContinuePlayPatch() {
  934. _classCallCheck(this, ContinuePlayPatch);
  935.  
  936. return _possibleConstructorReturn(this, (ContinuePlayPatch.__proto__ || Object.getPrototypeOf(ContinuePlayPatch)).call(this));
  937. }
  938.  
  939. _createClass(ContinuePlayPatch, [{
  940. key: '_apply',
  941. value: function _apply() {
  942. var _this18 = this;
  943.  
  944. Hooker.hookInitPlayerEvent(function (that) {
  945. // 视频播放结束处理
  946. that._player.control.on('ended', that._onEnd.bind(that));
  947. that._player.control.on('ended', function () {
  948. return _this18._onEnd(that);
  949. });
  950. });
  951. }
  952. }, {
  953. key: '_onEnd',
  954. value: function _onEnd(that) {
  955. var config = that.global.config;
  956. var playerState = that.global.playerState;
  957. if (config.continuePlay && config.nextVid && !playerState.fullscreen) {
  958. if (playerState.webfullscreen) {
  959. that.playByVid({ vid: that.global.config.nextVid });
  960. } else {
  961. that.gotoVideo(that.global.config.nextVid);
  962. }
  963. }
  964. }
  965. }]);
  966.  
  967. return ContinuePlayPatch;
  968. }(Patch);
  969.  
  970. var AutoSkipPatch = function (_Patch10) {
  971. _inherits(AutoSkipPatch, _Patch10);
  972.  
  973. function AutoSkipPatch() {
  974. _classCallCheck(this, AutoSkipPatch);
  975.  
  976. return _possibleConstructorReturn(this, (AutoSkipPatch.__proto__ || Object.getPrototypeOf(AutoSkipPatch)).call(this));
  977. }
  978.  
  979. _createClass(AutoSkipPatch, [{
  980. key: '_apply',
  981. value: function _apply() {
  982. Hooker.hookGlobalConstructorAfter(function (that) {
  983. return that.cycleData.isFront = true;
  984. });
  985. Hooker.hookGlobalResetAfter(function (that) {
  986. return that.cycleData.isFront = true;
  987. });
  988. }
  989. }]);
  990.  
  991. return AutoSkipPatch;
  992. }(Patch);
  993.  
  994. var FullscreenPatch = function (_Patch11) {
  995. _inherits(FullscreenPatch, _Patch11);
  996.  
  997. function FullscreenPatch() {
  998. _classCallCheck(this, FullscreenPatch);
  999.  
  1000. return _possibleConstructorReturn(this, (FullscreenPatch.__proto__ || Object.getPrototypeOf(FullscreenPatch)).call(this));
  1001. }
  1002.  
  1003. _createClass(FullscreenPatch, [{
  1004. key: '_apply',
  1005. value: function _apply() {
  1006. Object.defineProperty(document, 'fullscreen', {});
  1007. }
  1008. }]);
  1009.  
  1010. return FullscreenPatch;
  1011. }(Patch);
  1012.  
  1013. var WebFullscreen = function () {
  1014. function WebFullscreen(elem) {
  1015. _classCallCheck(this, WebFullscreen);
  1016.  
  1017. this._elem = elem;
  1018. }
  1019.  
  1020. _createClass(WebFullscreen, [{
  1021. key: 'isWebFullscreen',
  1022. value: function isWebFullscreen() {
  1023. return this._elem.classList.contains('webfullscreen');
  1024. }
  1025. }, {
  1026. key: 'enter',
  1027. value: function enter() {
  1028. this._elem.classList.add('webfullscreen');
  1029. document.body.style.overflow = 'hidden';
  1030.  
  1031. var parentNode = this._elem.parentNode;
  1032. while (parentNode.nodeName !== 'BODY') {
  1033. if (parentNode.nodeType === Node.ELEMENT_NODE) {
  1034. parentNode.classList.add('z-top');
  1035. }
  1036. parentNode = parentNode.parentNode;
  1037. }
  1038. }
  1039. }, {
  1040. key: 'exit',
  1041. value: function exit() {
  1042. this._elem.classList.remove('webfullscreen');
  1043. document.body.style.overflow = '';
  1044.  
  1045. var parentNode = this._elem.parentNode;
  1046. while (parentNode.nodeName !== 'BODY') {
  1047. if (parentNode.nodeType === Node.ELEMENT_NODE) {
  1048. parentNode.classList.remove('z-top');
  1049. }
  1050. parentNode = parentNode.parentNode;
  1051. }
  1052. }
  1053. }, {
  1054. key: 'toggle',
  1055. value: function toggle() {
  1056. this.isWebFullscreen() ? this.exit() : this.enter();
  1057. }
  1058. }], [{
  1059. key: 'addStyle',
  1060. value: function addStyle() {
  1061. 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 ');
  1062. }
  1063. }]);
  1064.  
  1065. return WebFullscreen;
  1066. }();
  1067.  
  1068. var ManagePatch = function (_Patch12) {
  1069. _inherits(ManagePatch, _Patch12);
  1070.  
  1071. function ManagePatch() {
  1072. _classCallCheck(this, ManagePatch);
  1073.  
  1074. return _possibleConstructorReturn(this, (ManagePatch.__proto__ || Object.getPrototypeOf(ManagePatch)).call(this));
  1075. }
  1076.  
  1077. _createClass(ManagePatch, [{
  1078. key: '_apply',
  1079. value: function _apply() {
  1080. this._prepare();
  1081. this._hookManage();
  1082. }
  1083. }, {
  1084. key: '_prepare',
  1085. value: function _prepare() {
  1086. this._customTip();
  1087. this._disablePlayAfterSeek();
  1088. this._addPrevInfo();
  1089. this._playAfterPlayerReset();
  1090. new ContinuePlayPatch().install();
  1091. new SkipLocalPlayRecordPatch().install();
  1092. new FullscreenPatch().install();
  1093. }
  1094. }, {
  1095. key: '_customTip',
  1096. value: function _customTip() {
  1097. Hooker.hookTips(function (exports) {
  1098. var showHintTips = exports.default.prototype.showHintTips;
  1099. exports.default.prototype.showHintTips = function (code, info) {
  1100. if (info.msg) {
  1101. this._hintLayer.setHintShow(info.msg);
  1102. } else {
  1103. showHintTips.apply(this, [code, info]);
  1104. }
  1105. };
  1106. });
  1107. }
  1108. }, {
  1109. key: '_disablePlayAfterSeek',
  1110. value: function _disablePlayAfterSeek() {
  1111. // SingleVideoControl seek 后不自动播放
  1112. Hooker.hookBase(function (exports) {
  1113. var _setCurrentTime = exports.SingleVideoControl.prototype._setCurrentTime;
  1114. exports.SingleVideoControl.prototype._setCurrentTime = function (time) {
  1115. var play = this.video.play;
  1116. this.video.play = function () {};
  1117. _setCurrentTime.apply(this, [time]);
  1118. this.video.play = play;
  1119. };
  1120. });
  1121. }
  1122. }, {
  1123. key: '_addPrevInfo',
  1124. value: function _addPrevInfo() {
  1125. Hooker.hookGlobalDeal(function (that) {
  1126. if (that.ups && that.ups.videoData && that.ups.programList && that.ups.programList.videoList) {
  1127. var list = that.ups.programList.videoList;
  1128. var currVid = that.ups.videoData.id;
  1129. var currIdx = list.findIndex(function (item) {
  1130. return parseInt(item.vid) === currVid;
  1131. });
  1132. if (currIdx > 0) {
  1133. var prevVideo = list[currIdx - 1];
  1134. that.ups.programList.prevVideo = prevVideo;
  1135. prevVideo && (that._config.prevVid = prevVideo.encodevid);
  1136. }
  1137. }
  1138. });
  1139. }
  1140. }, {
  1141. key: '_playAfterPlayerReset',
  1142. value: function _playAfterPlayerReset() {
  1143. Hooker.hookResetPlayerAfter(function (that) {
  1144. if (that.global.playerState.state === 'playerreset') that.play();
  1145. });
  1146. }
  1147. }, {
  1148. key: '_hookManage',
  1149. value: function _hookManage() {
  1150. Hooker.hookManage(this._hookManageCallback.bind(this));
  1151. }
  1152. }, {
  1153. key: '_hookManageCallback',
  1154. value: function _hookManageCallback(exports) {
  1155. var proto = exports.default.prototype;
  1156.  
  1157. var _init = proto._init;
  1158. proto._init = function () {
  1159. _init.apply(this);
  1160. WebFullscreen.addStyle();
  1161. this._webfullscreen = new WebFullscreen(this.container);
  1162. };
  1163.  
  1164. proto._showTip = function (msg) {
  1165. this._emitter.emit('player.showinfo', { type: 'hint', msg: msg });
  1166. };
  1167.  
  1168. proto.play = function () {
  1169. this._player && this._player.control.play();
  1170. this._showTip('播放');
  1171. };
  1172.  
  1173. proto._pause = proto.pause;
  1174. proto.pause = function () {
  1175. this._pause();
  1176. this._showTip('暂停');
  1177. };
  1178.  
  1179. proto.adjustVolume = function (value) {
  1180. var volume = this.global.playerState.volume + value;
  1181. volume = Math.max(0, Math.min(1, volume.toFixed(2)));
  1182. this._player.control.setVolume(volume);
  1183. if (volume === 0) {
  1184. this._emitter.emit('player.showinfo', { type: 'hint', code: 'H0003', volume: volume + '%' });
  1185. }
  1186. };
  1187.  
  1188. proto.toggleMute = function () {
  1189. if (this.global.playerState.muted) this._showTip('取消静音');
  1190. this.setMuted(!this.global.playerState.muted);
  1191. };
  1192.  
  1193. proto.stepSeek = function (stepTime) {
  1194. var duration = this._player.control.getDuration();
  1195. var currentTime = this.global.currentTime;
  1196. var seekTime = Math.max(0, Math.min(duration, currentTime + stepTime));
  1197. this.seek(seekTime);
  1198.  
  1199. var msg = void 0;
  1200. if (Math.abs(stepTime) < 60) {
  1201. msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime + '\u79D2' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) + '\u79D2';
  1202. } else {
  1203. msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime / 60 + '\u5206\u949F' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) / 60 + '\u5206\u949F';
  1204. }
  1205. this._showTip(msg);
  1206. };
  1207.  
  1208. proto.rangeSeek = function (range) {
  1209. var duration = this._player.control.getDuration();
  1210. var seekTime = Math.max(0, Math.min(duration, duration * range));
  1211. this.seek(seekTime);
  1212. this._showTip('定位:' + (range * 100).toFixed(0) + '%');
  1213. };
  1214.  
  1215. proto.isFullscreen = function () {
  1216. return this.global.playerState.fullscreen;
  1217. };
  1218.  
  1219. proto.toggleFullscreen = function () {
  1220. if (this.isFullscreen()) {
  1221. this.exitFullscreen();
  1222. } else {
  1223. this.fullScreen();
  1224. }
  1225. };
  1226.  
  1227. proto.isWebFullscreen = function () {
  1228. return this._webfullscreen.isWebFullscreen();
  1229. };
  1230.  
  1231. proto.enterWebFullscreen = function () {
  1232. this._webfullscreen.enter();
  1233. this.global.playerState = { webfullscreen: true };
  1234. this._player.control.emit('webfullscreen', true);
  1235. };
  1236.  
  1237. proto.exitWebFullscreen = function () {
  1238. this._webfullscreen.exit();
  1239. this.global.playerState = { webfullscreen: false };
  1240. this._player.control.emit('webfullscreen', false);
  1241. };
  1242.  
  1243. proto.toggleWebFullscreen = function () {
  1244. this.isWebFullscreen() ? this.exitWebFullscreen() : this.enterWebFullscreen();
  1245. };
  1246.  
  1247. proto.adjustPlaybackRate = function (value) {
  1248. var videoCore = this._player.control._videoCore;
  1249. var rate = Math.max(0.2, Math.min(5, videoCore.video.playbackRate + value));
  1250. if (this._player.config.controlType === 'multi') {
  1251. videoCore._videoElments.forEach(function (v) {
  1252. return v.playbackRate = rate;
  1253. });
  1254. } else {
  1255. videoCore.video.playbackRate = rate;
  1256. }
  1257. this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate.toFixed(1).replace(/\.0+$/, ''));
  1258. };
  1259.  
  1260. proto.resetPlaybackRate = function () {
  1261. this._player.control.setRate(1);
  1262. this._showTip('恢复播放速率');
  1263. };
  1264.  
  1265. proto.getFps = function () {
  1266. return 25; // 标清fps为15,标清以上fps为25。
  1267. };
  1268.  
  1269. proto.prevFrame = function () {
  1270. var state = this.global.playerState.state;
  1271. if (state === 'playing') this.pause();
  1272. var duration = this._player.control.getDuration();
  1273. var currentTime = this.global.currentTime;
  1274. var seekTime = Math.max(0, Math.min(duration, currentTime - 1 / this.getFps()));
  1275. this.seek(seekTime);
  1276. this._showTip('上一帧');
  1277. };
  1278.  
  1279. proto.nextFrame = function () {
  1280. var state = this.global.playerState.state;
  1281. if (state === 'playing') this.pause();
  1282. var duration = this._player.control.getDuration();
  1283. var currentTime = this.global.currentTime;
  1284. var seekTime = Math.max(0, Math.min(duration, currentTime + 1 / this.getFps()));
  1285. this.seek(seekTime);
  1286. this._showTip('下一帧');
  1287. };
  1288.  
  1289. proto.playPrev = function () {
  1290. var prevVid = this.global.config.prevVid;
  1291. if (prevVid) {
  1292. if (this.isFullscreen() || this.isWebFullscreen()) {
  1293. this.playByVid({ vid: prevVid });
  1294. } else {
  1295. this.gotoVideo(prevVid);
  1296. }
  1297. this._showTip('播放上一集');
  1298. } else {
  1299. this._showTip('没有上一集哦');
  1300. }
  1301. };
  1302.  
  1303. var playNext = proto.playNext;
  1304. proto.playNext = function (data) {
  1305. if (data) return playNext.apply(this, [data]);
  1306. var nextVid = this.global.config.nextVid;
  1307. if (nextVid) {
  1308. if (this.isFullscreen() || this.isWebFullscreen()) {
  1309. this.playByVid({ vid: nextVid });
  1310. } else {
  1311. this.gotoVideo(nextVid);
  1312. }
  1313. this._showTip('播放下一集');
  1314. } else {
  1315. this._showTip('没有下一集哦');
  1316. }
  1317. };
  1318.  
  1319. proto.gotoVideo = function (vid) {
  1320. location.href = '//v.youku.com/v_show/id_' + vid + '.html';
  1321. };
  1322. }
  1323. }]);
  1324.  
  1325. return ManagePatch;
  1326. }(Patch);
  1327.  
  1328. var managePatch = new ManagePatch();
  1329.  
  1330. var KeyShortcutsPatch = function (_Patch13) {
  1331. _inherits(KeyShortcutsPatch, _Patch13);
  1332.  
  1333. function KeyShortcutsPatch() {
  1334. _classCallCheck(this, KeyShortcutsPatch);
  1335.  
  1336. return _possibleConstructorReturn(this, (KeyShortcutsPatch.__proto__ || Object.getPrototypeOf(KeyShortcutsPatch)).call(this));
  1337. }
  1338.  
  1339. _createClass(KeyShortcutsPatch, [{
  1340. key: '_apply',
  1341. value: function _apply() {
  1342. this._prepare();
  1343. this._addListener();
  1344. }
  1345. }, {
  1346. key: '_prepare',
  1347. value: function _prepare() {
  1348. managePatch.install();
  1349. this._obtainPlayer();
  1350. }
  1351. }, {
  1352. key: '_obtainPlayer',
  1353. value: function _obtainPlayer() {
  1354. var self = this;
  1355. Hooker.hookKeyShortcuts(function (exports) {
  1356. exports.default.prototype.registerEvents = function () {
  1357. self._player = this._player;
  1358. };
  1359. });
  1360. }
  1361. }, {
  1362. key: '_addListener',
  1363. value: function _addListener() {
  1364. document.addEventListener('keydown', this._handler.bind(this));
  1365. }
  1366. }, {
  1367. key: '_handler',
  1368. value: function _handler(event) {
  1369. if (event.target.nodeName !== 'BODY') return;
  1370.  
  1371. switch (event.keyCode) {
  1372. case 32:
  1373. // Spacebar
  1374. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1375. var state = this._player.global.playerState.state;
  1376. if (state === 'paused') {
  1377. this._player.play();
  1378. } else if (state === 'ended') {
  1379. this._player.replay();
  1380. } else {
  1381. this._player.pause();
  1382. }
  1383. } else {
  1384. return;
  1385. }
  1386. break;
  1387. case 39: // → Arrow Right
  1388. case 37:
  1389. {
  1390. // ← Arrow Left
  1391. var stepTime = void 0;
  1392. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1393. stepTime = 39 === event.keyCode ? 5 : -5;
  1394. } else if (event.ctrlKey && !event.shiftKey && !event.altKey) {
  1395. stepTime = 39 === event.keyCode ? 30 : -30;
  1396. } else if (!event.ctrlKey && event.shiftKey && !event.altKey) {
  1397. stepTime = 39 === event.keyCode ? 60 : -60;
  1398. } else if (event.ctrlKey && !event.shiftKey && event.altKey) {
  1399. stepTime = 39 === event.keyCode ? 3e2 : -3e2; // 5分钟
  1400. } else {
  1401. return;
  1402. }
  1403. this._player.stepSeek(stepTime);
  1404. break;
  1405. }
  1406. case 38: // ↑ Arrow Up
  1407. case 40:
  1408. // ↓ Arrow Down
  1409. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1410. this._player.adjustVolume(38 === event.keyCode ? 0.05 : -0.05);
  1411. } else {
  1412. return;
  1413. }
  1414. break;
  1415. case 77:
  1416. // M
  1417. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1418. this._player.toggleMute();
  1419. } else {
  1420. return;
  1421. }
  1422. break;
  1423. case 13:
  1424. // Enter
  1425. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1426. this._player.toggleFullscreen();
  1427. } else if (event.ctrlKey && !event.shiftKey && !event.altKey) {
  1428. this._player.toggleWebFullscreen();
  1429. } else {
  1430. return;
  1431. }
  1432. break;
  1433. case 67: // C
  1434. case 88:
  1435. // X
  1436. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1437. this._player.adjustPlaybackRate(67 === event.keyCode ? 0.1 : -0.1);
  1438. } else {
  1439. return;
  1440. }
  1441. break;
  1442. case 90:
  1443. // Z
  1444. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1445. this._player.resetPlaybackRate();
  1446. } else {
  1447. return;
  1448. }
  1449. break;
  1450. case 68: // D
  1451. case 70:
  1452. // F
  1453. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1454. if (event.keyCode === 68) {
  1455. this._player.prevFrame();
  1456. } else {
  1457. this._player.nextFrame();
  1458. }
  1459. } else {
  1460. return;
  1461. }
  1462. break;
  1463. case 80: // P
  1464. case 78:
  1465. // N
  1466. if (!event.ctrlKey && event.shiftKey && !event.altKey) {
  1467. if (event.keyCode === 78) {
  1468. this._player.playNext();
  1469. } else {
  1470. this._player.playPrev();
  1471. }
  1472. } else {
  1473. return;
  1474. }
  1475. break;
  1476. case 27:
  1477. // ESC
  1478. if (!event.ctrlKey && !event.shiftKey && !event.altKey) this._player.isWebFullscreen() && this._player.exitWebFullscreen();
  1479. return;
  1480. default:
  1481. if (event.keyCode >= 48 && event.keyCode <= 57) {
  1482. // 0 ~ 9
  1483. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1484. this._player.rangeSeek((event.keyCode - 48) * 0.1);
  1485. } else {
  1486. return;
  1487. }
  1488. } else {
  1489. return;
  1490. }
  1491. }
  1492.  
  1493. event.preventDefault();
  1494. event.stopPropagation();
  1495. }
  1496. }]);
  1497.  
  1498. return KeyShortcutsPatch;
  1499. }(Patch);
  1500.  
  1501. var MouseShortcutsPatch = function (_Patch14) {
  1502. _inherits(MouseShortcutsPatch, _Patch14);
  1503.  
  1504. function MouseShortcutsPatch() {
  1505. _classCallCheck(this, MouseShortcutsPatch);
  1506.  
  1507. return _possibleConstructorReturn(this, (MouseShortcutsPatch.__proto__ || Object.getPrototypeOf(MouseShortcutsPatch)).call(this));
  1508. }
  1509.  
  1510. _createClass(MouseShortcutsPatch, [{
  1511. key: '_apply',
  1512. value: function _apply() {
  1513. this._prepare();
  1514. this._addListener();
  1515. }
  1516. }, {
  1517. key: '_prepare',
  1518. value: function _prepare() {
  1519. managePatch.install();
  1520. this._addStyle();
  1521. }
  1522. }, {
  1523. key: '_addStyle',
  1524. value: function _addStyle() {
  1525. GM_addStyle('\n .h5-layer-conatiner {\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n user-select: none !important;\n }\n .h5-ext-layer-adsdk {\n display: none !important;\n }\n ');
  1526. }
  1527. }, {
  1528. key: '_addListener',
  1529. value: function _addListener() {
  1530. Hooker.hookInitPlayerEvent(function (that) {
  1531. var timer = void 0;
  1532. var container = that.container.querySelector('.h5-layer-conatiner');
  1533. container.addEventListener('click', function (event) {
  1534. if (this !== event.target) return;
  1535. if (timer) {
  1536. clearTimeout(timer);
  1537. timer = null;
  1538. return;
  1539. }
  1540. timer = setTimeout(function () {
  1541. var state = that.global.playerState.state;
  1542. if (state === 'paused') {
  1543. that.play();
  1544. } else if (state === 'ended') {
  1545. that.replay();
  1546. } else {
  1547. that.pause();
  1548. }
  1549. timer = null;
  1550. }, 200);
  1551. });
  1552. container.addEventListener('dblclick', function (event) {
  1553. if (this !== event.target) return;
  1554. event.ctrlKey ? that.toggleWebFullscreen() : that.toggleFullscreen();
  1555. });
  1556. container.addEventListener('wheel', function (event) {
  1557. if (this === event.target && (that.isFullscreen() || that.isWebFullscreen())) {
  1558. var delta = event.wheelDelta || event.detail || event.deltaY && -event.deltaY;
  1559. that.adjustVolume(delta > 0 ? 0.05 : -0.05);
  1560. }
  1561. });
  1562. container = null;
  1563. });
  1564. }
  1565. }]);
  1566.  
  1567. return MouseShortcutsPatch;
  1568. }(Patch);
  1569.  
  1570. var ShortcutsPatch = function (_Patch15) {
  1571. _inherits(ShortcutsPatch, _Patch15);
  1572.  
  1573. function ShortcutsPatch() {
  1574. _classCallCheck(this, ShortcutsPatch);
  1575.  
  1576. return _possibleConstructorReturn(this, (ShortcutsPatch.__proto__ || Object.getPrototypeOf(ShortcutsPatch)).call(this));
  1577. }
  1578.  
  1579. _createClass(ShortcutsPatch, [{
  1580. key: '_apply',
  1581. value: function _apply() {
  1582. new KeyShortcutsPatch().install();
  1583. Logger.log('添加键盘快捷键');
  1584. new MouseShortcutsPatch().install();
  1585. Logger.log('添加鼠标快捷键');
  1586. }
  1587. }]);
  1588.  
  1589. return ShortcutsPatch;
  1590. }(Patch);
  1591.  
  1592. // class H5Patch extends Patch {
  1593.  
  1594. // constructor() {
  1595. // super();
  1596. // }
  1597.  
  1598. // _apply() {
  1599. // Hooker.hookDefine('page/find/play/player/load', this._forceH5.bind(this));
  1600. // }
  1601.  
  1602. // _forceH5(code) {
  1603. // return code.replace(/(if\s*\().*?(\)\s*\{)/, '$1true$2').replace('window.sessionStorage', 'null');
  1604. // }
  1605.  
  1606. // }
  1607.  
  1608. function ensureH5PlayerEnabled() {
  1609. // (new H5Patch()).install();
  1610. unsafeWindow.navigator.plugins['Shockwave Flash'] = undefined;
  1611. Logger.log('启用html5播放器');
  1612. }
  1613.  
  1614. function blockAds() {
  1615. new AdBlockPatch().install();
  1616. Logger.log('和谐广告');
  1617. }
  1618.  
  1619. function fixAutoSkip() {
  1620. new AutoSkipPatch().install();
  1621. Logger.log('修复跳过片头片尾、播放记录');
  1622. }
  1623.  
  1624. function invalidateWatermarks() {
  1625. new WatermarksPatch().install();
  1626. Logger.log('和谐水印');
  1627. }
  1628.  
  1629. function invalidateQualityLimitation() {
  1630. new VipPatch().install();
  1631. Logger.log('解除会员画质限制');
  1632. }
  1633.  
  1634. function improveQualityLogic() {
  1635. new QualityPatch().install();
  1636. Logger.log('改善画质逻辑');
  1637. }
  1638.  
  1639. function improveAutoHide() {
  1640. new DashboardPatch().install();
  1641. new TopAreaPatch().install();
  1642. new SettingSeriesPatch().install();
  1643. Logger.log('改善控件与光标自动隐藏');
  1644. }
  1645.  
  1646. function improveShortcuts() {
  1647. new ShortcutsPatch().install();
  1648. }
  1649.  
  1650. //=============================================================================
  1651.  
  1652. ensureH5PlayerEnabled();
  1653. blockAds();
  1654. fixAutoSkip();
  1655. invalidateWatermarks();
  1656. invalidateQualityLimitation();
  1657. improveQualityLogic();
  1658. improveAutoHide();
  1659. improveShortcuts();
  1660. })();