ykh5p

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

目前为 2017-08-30 提交的版本。查看 最新版本

  1. 'use strict';
  2.  
  3. 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; }; }();
  4.  
  5. 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; }
  6.  
  7. 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; }
  8.  
  9. 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); } }
  10.  
  11. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  12.  
  13. // ==UserScript==
  14. // @name ykh5p
  15. // @namespace https://github.com/gooyie/ykh5p
  16. // @homepageURL https://github.com/gooyie/ykh5p
  17. // @supportURL https://github.com/gooyie/ykh5p/issues
  18. // @version 0.7.0
  19. // @description 改善优酷官方html5播放器播放体验
  20. // @author gooyie
  21. // @license MIT License
  22. //
  23. // @include *://v.youku.com/*
  24. // @grant GM_info
  25. // @grant GM_addStyle
  26. // @grant unsafeWindow
  27. // @run-at document-start
  28. // ==/UserScript==
  29.  
  30. (function () {
  31. 'use strict';
  32.  
  33. /* eslint-disable no-console */
  34.  
  35. var Logger = function () {
  36. function Logger() {
  37. _classCallCheck(this, Logger);
  38. }
  39.  
  40. _createClass(Logger, null, [{
  41. key: 'log',
  42. value: function log() {
  43. var _console;
  44.  
  45. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  46. args[_key] = arguments[_key];
  47. }
  48.  
  49. (_console = console).log.apply(_console, ['%c' + this.tag + '%c' + args.shift(), 'color: #fff; background: #2FB3FF', ''].concat(args));
  50. }
  51. }, {
  52. key: 'info',
  53. value: function info() {
  54. var _console2;
  55.  
  56. for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  57. args[_key2] = arguments[_key2];
  58. }
  59.  
  60. (_console2 = console).info.apply(_console2, [this.tag + args.shift()].concat(args));
  61. }
  62. }, {
  63. key: 'debug',
  64. value: function debug() {
  65. var _console3;
  66.  
  67. for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
  68. args[_key3] = arguments[_key3];
  69. }
  70.  
  71. (_console3 = console).debug.apply(_console3, [this.tag + args.shift()].concat(args));
  72. }
  73. }, {
  74. key: 'warn',
  75. value: function warn() {
  76. var _console4;
  77.  
  78. for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
  79. args[_key4] = arguments[_key4];
  80. }
  81.  
  82. (_console4 = console).warn.apply(_console4, [this.tag + args.shift()].concat(args));
  83. }
  84. }, {
  85. key: 'error',
  86. value: function error() {
  87. var _console5;
  88.  
  89. for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
  90. args[_key5] = arguments[_key5];
  91. }
  92.  
  93. (_console5 = console).error.apply(_console5, [this.tag + args.shift()].concat(args));
  94. }
  95. }, {
  96. key: 'tag',
  97. get: function get() {
  98. return '[' + GM_info.script.name + ']';
  99. }
  100. }]);
  101.  
  102. return Logger;
  103. }();
  104. /* eslint-enable no-console */
  105.  
  106. var Hooker = function () {
  107. function Hooker() {
  108. _classCallCheck(this, Hooker);
  109. }
  110.  
  111. _createClass(Hooker, null, [{
  112. key: 'hookCall',
  113. value: function hookCall() {
  114. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  115.  
  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.apply(undefined, args);
  125. } catch (err) {
  126. Logger.error(err.stack);
  127. }
  128. return ret;
  129. };
  130.  
  131. Function.prototype.call.toString = Function.prototype.call.toLocaleString = function () {
  132. return 'function call() { [native code] }';
  133. };
  134. }
  135. }, {
  136. key: '_isEsModule',
  137. value: function _isEsModule(obj) {
  138. return obj && obj.__esModule;
  139. }
  140. }, {
  141. key: '_isFuction',
  142. value: function _isFuction(arg) {
  143. return 'function' === typeof arg;
  144. }
  145. }, {
  146. key: '_isFactoryCall',
  147. value: function _isFactoryCall(args) {
  148. // module.exports, module, module.exports, require
  149. return args.length === 4 && args[1] instanceof Object && args[1].hasOwnProperty('exports');
  150. }
  151. }, {
  152. key: 'hookFactoryCall',
  153. value: function hookFactoryCall() {
  154. var _this = this;
  155.  
  156. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  157.  
  158. this.hookCall(function () {
  159. for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
  160. args[_key7] = arguments[_key7];
  161. }
  162.  
  163. if (_this._isFactoryCall(args)) cb.apply(undefined, args);
  164. });
  165. }
  166. }, {
  167. key: '_isUpsFactoryCall',
  168. value: function _isUpsFactoryCall() {
  169. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  170.  
  171. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('getServieceUrl') && /\.id\s*=\s*"ups"/.test(exports.default.toString());
  172. }
  173. }, {
  174. key: 'hookUps',
  175. value: function hookUps() {
  176. var _this2 = this;
  177.  
  178. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  179.  
  180. this.hookFactoryCall(function () {
  181. for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
  182. args[_key8] = arguments[_key8];
  183. }
  184.  
  185. if (_this2._isUpsFactoryCall(args[1].exports)) cb(args[1].exports);
  186. });
  187. }
  188. }, {
  189. key: 'hookUpsOnComplete',
  190. value: function hookUpsOnComplete() {
  191. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  192.  
  193. this.hookUps(function (exports) {
  194. var onComplete = exports.default.prototype.onComplete;
  195. exports.default.prototype.onComplete = function (res) {
  196. cb(res);
  197. onComplete.apply(this, [res]);
  198. };
  199. });
  200. }
  201. }, {
  202. key: '_isLogoFactoryCall',
  203. value: function _isLogoFactoryCall() {
  204. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  205.  
  206. 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());
  207. }
  208. }, {
  209. key: 'hookLogo',
  210. value: function hookLogo() {
  211. var _this3 = this;
  212.  
  213. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  214.  
  215. this.hookFactoryCall(function () {
  216. for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
  217. args[_key9] = arguments[_key9];
  218. }
  219.  
  220. if (_this3._isLogoFactoryCall(args[1].exports)) cb(args[1].exports);
  221. });
  222. }
  223. }, {
  224. key: '_isSettingFactoryCall',
  225. value: function _isSettingFactoryCall() {
  226. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  227.  
  228. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setQuality');
  229. }
  230. }, {
  231. key: 'hookSetting',
  232. value: function hookSetting() {
  233. var _this4 = this;
  234.  
  235. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  236.  
  237. this.hookFactoryCall(function () {
  238. for (var _len10 = arguments.length, args = Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
  239. args[_key10] = arguments[_key10];
  240. }
  241.  
  242. if (_this4._isSettingFactoryCall(args[1].exports)) cb(args[1].exports);
  243. });
  244. }
  245. }, {
  246. key: 'hookRenderQulaity',
  247. value: function hookRenderQulaity() {
  248. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  249.  
  250. Hooker.hookSetting(function (exports) {
  251. var renderQulaity = exports.default.prototype.renderQulaity;
  252. exports.default.prototype.renderQulaity = function (qualitys) {
  253. cb(qualitys, this);
  254. renderQulaity.apply(this, [qualitys]);
  255. };
  256. });
  257. }
  258. }, {
  259. key: 'hookSetCurrentQuality',
  260. value: function hookSetCurrentQuality() {
  261. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  262.  
  263. Hooker.hookSetting(function (exports) {
  264. var setCurrentQuality = exports.default.prototype.setCurrentQuality;
  265. exports.default.prototype.setCurrentQuality = function () {
  266. cb(this);
  267. setCurrentQuality.apply(this);
  268. };
  269. });
  270. }
  271. }, {
  272. key: '_isPlayerFactoryCall',
  273. value: function _isPlayerFactoryCall() {
  274. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  275.  
  276. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_resetPlayer');
  277. }
  278. }, {
  279. key: 'hookPlayer',
  280. value: function hookPlayer() {
  281. var _this5 = this;
  282.  
  283. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  284.  
  285. this.hookFactoryCall(function () {
  286. for (var _len11 = arguments.length, args = Array(_len11), _key11 = 0; _key11 < _len11; _key11++) {
  287. args[_key11] = arguments[_key11];
  288. }
  289.  
  290. if (_this5._isPlayerFactoryCall(args[1].exports)) cb(args[1].exports);
  291. });
  292. }
  293. }, {
  294. key: 'hookPlayerInitServiceEvent',
  295. value: function hookPlayerInitServiceEvent() {
  296. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  297.  
  298. Hooker.hookPlayer(function (exports) {
  299. var _initServiceEvent = exports.default.prototype._initServiceEvent;
  300. exports.default.prototype._initServiceEvent = function () {
  301. cb(this);
  302. _initServiceEvent.apply(this);
  303. };
  304. });
  305. }
  306. }, {
  307. key: '_isKeyShortcutsFactoryCall',
  308. value: function _isKeyShortcutsFactoryCall() {
  309. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  310.  
  311. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('registerEvents');
  312. }
  313. }, {
  314. key: 'hookKeyShortcuts',
  315. value: function hookKeyShortcuts() {
  316. var _this6 = this;
  317.  
  318. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  319.  
  320. this.hookFactoryCall(function () {
  321. for (var _len12 = arguments.length, args = Array(_len12), _key12 = 0; _key12 < _len12; _key12++) {
  322. args[_key12] = arguments[_key12];
  323. }
  324.  
  325. if (_this6._isKeyShortcutsFactoryCall(args[1].exports)) cb(args[1].exports);
  326. });
  327. }
  328. }, {
  329. key: '_isTipsFactoryCall',
  330. value: function _isTipsFactoryCall() {
  331. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  332.  
  333. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showHintTips');
  334. }
  335. }, {
  336. key: 'hookTips',
  337. value: function hookTips() {
  338. var _this7 = this;
  339.  
  340. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  341.  
  342. this.hookFactoryCall(function () {
  343. for (var _len13 = arguments.length, args = Array(_len13), _key13 = 0; _key13 < _len13; _key13++) {
  344. args[_key13] = arguments[_key13];
  345. }
  346.  
  347. if (_this7._isTipsFactoryCall(args[1].exports)) cb(args[1].exports);
  348. });
  349. }
  350. }, {
  351. key: '_isAdServiceFactoryCall',
  352. value: function _isAdServiceFactoryCall() {
  353. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  354.  
  355. return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('requestAdData');
  356. }
  357. }, {
  358. key: 'hookAdService',
  359. value: function hookAdService() {
  360. var _this8 = this;
  361.  
  362. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  363.  
  364. this.hookFactoryCall(function () {
  365. for (var _len14 = arguments.length, args = Array(_len14), _key14 = 0; _key14 < _len14; _key14++) {
  366. args[_key14] = arguments[_key14];
  367. }
  368.  
  369. if (_this8._isAdServiceFactoryCall(args[1].exports)) cb(args[1].exports);
  370. });
  371. }
  372. }, {
  373. key: '_extractArgsName',
  374. value: function _extractArgsName(code) {
  375. return code.slice(code.indexOf('(') + 1, code.indexOf(')')).split(/\s*,\s*/);
  376. }
  377. }, {
  378. key: '_extractFunctionBody',
  379. value: function _extractFunctionBody(code) {
  380. return code.slice(code.indexOf('{') + 1, code.lastIndexOf('}'));
  381. }
  382. }, {
  383. key: '_isGlobalFactoryCall',
  384. value: function _isGlobalFactoryCall() {
  385. var exports = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  386.  
  387. return exports.SingleVideoControl && exports.MultiVideoControl;
  388. }
  389. }, {
  390. key: 'hookGlobal',
  391. value: function hookGlobal() {
  392. var _this9 = this;
  393.  
  394. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  395. var mode = arguments[1];
  396.  
  397. if (!this._hookGlobalCallbacks) {
  398. this._hookGlobalCallbacks = [];
  399. this._hookGlobalCodeCallbacks = [];
  400. (mode === 'code' ? this._hookGlobalCodeCallbacks : this._hookGlobalCallbacks).push(cb);
  401.  
  402. this.hookFactoryCall(function () {
  403. for (var _len15 = arguments.length, args = Array(_len15), _key15 = 0; _key15 < _len15; _key15++) {
  404. args[_key15] = arguments[_key15];
  405. }
  406.  
  407. if (_this9._isGlobalFactoryCall(args[1].exports)) {
  408. if (_this9._hookGlobalCodeCallbacks.length > 0) {
  409. var code = args[3].m[args[1].i].toString();
  410. code = _this9._hookGlobalCodeCallbacks.reduce(function (c, cb) {
  411. return cb(c);
  412. }, code);
  413. var fn = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(_this9._extractArgsName(code)), [_this9._extractFunctionBody(code)])))();
  414. fn.apply(args[0], args.slice(1));
  415. }
  416. _this9._hookGlobalCallbacks.forEach(function (cb) {
  417. return cb(args[1].exports);
  418. });
  419. }
  420. });
  421. } else {
  422. (mode === 'code' ? this._hookGlobalCodeCallbacks : this._hookGlobalCallbacks).push(cb);
  423. }
  424. }
  425. }, {
  426. key: 'hookOz',
  427. value: function hookOz() {
  428. var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
  429.  
  430. if (!this._hookOzCallbacks) {
  431. var self = this;
  432. this._hookOzCallbacks = [cb];
  433. var window = unsafeWindow;
  434. var oz = window.oz; // oz 可能先于脚本执行
  435.  
  436. Reflect.defineProperty(window, 'oz', {
  437. get: function get() {
  438. return oz;
  439. },
  440. set: function set(value) {
  441. oz = value;
  442. try {
  443. self._hookOzCallbacks.forEach(function (cb) {
  444. return cb(oz);
  445. });
  446. } catch (err) {
  447. Logger.error(err.stack);
  448. }
  449. }
  450. });
  451.  
  452. if (oz) window.oz = oz; // oz 先于脚本执行
  453. } else {
  454. this._hookOzCallbacks.push(cb);
  455. }
  456. }
  457. }, {
  458. key: 'hookDefine',
  459. value: function hookDefine(name) {
  460. var _this10 = this;
  461.  
  462. var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
  463.  
  464. if (!this._hookDefineCallbacksMap) {
  465. this._hookDefineCallbacksMap = new Map([[name, [cb]]]);
  466. this.hookOz(function (oz) {
  467. var self = _this10;
  468. var define = oz.define;
  469. oz.define = function (name, deps, block) {
  470. if (self._hookDefineCallbacksMap.has(name)) {
  471. var code = block.toString();
  472. code = self._hookDefineCallbacksMap.get(name).reduce(function (c, cb) {
  473. return cb(c);
  474. }, code);
  475. block = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(self._extractArgsName(code)), [self._extractFunctionBody(code)])))();
  476. }
  477. define(name, deps, block);
  478. };
  479. });
  480. } else {
  481. if (this._hookDefineCallbacksMap.has(name)) {
  482. this._hookDefineCallbacksMap.get(name).push(cb);
  483. } else {
  484. this._hookDefineCallbacksMap.set(name, [cb]);
  485. }
  486. }
  487. }
  488. }]);
  489.  
  490. return Hooker;
  491. }();
  492.  
  493. var Patch = function () {
  494. function Patch() {
  495. _classCallCheck(this, Patch);
  496.  
  497. this._installed = false;
  498. }
  499.  
  500. _createClass(Patch, [{
  501. key: 'install',
  502. value: function install() {
  503. if (!this._installed) {
  504. this._installed = true;
  505. this._apply();
  506. }
  507. }
  508. }, {
  509. key: '_apply',
  510. value: function _apply() {}
  511. }]);
  512.  
  513. return Patch;
  514. }();
  515.  
  516. var AdBlockPatch = function (_Patch) {
  517. _inherits(AdBlockPatch, _Patch);
  518.  
  519. function AdBlockPatch() {
  520. _classCallCheck(this, AdBlockPatch);
  521.  
  522. return _possibleConstructorReturn(this, (AdBlockPatch.__proto__ || Object.getPrototypeOf(AdBlockPatch)).call(this));
  523. }
  524.  
  525. _createClass(AdBlockPatch, [{
  526. key: '_apply',
  527. value: function _apply() {
  528. Hooker.hookAdService(function (exports) {
  529. exports.default.prototype.requestAdData = function (arg) {
  530. this.fail(arg, { code: '404', message: 'error' });
  531. };
  532. });
  533. }
  534. }]);
  535.  
  536. return AdBlockPatch;
  537. }(Patch);
  538.  
  539. var WatermarksPatch = function (_Patch2) {
  540. _inherits(WatermarksPatch, _Patch2);
  541.  
  542. function WatermarksPatch() {
  543. _classCallCheck(this, WatermarksPatch);
  544.  
  545. return _possibleConstructorReturn(this, (WatermarksPatch.__proto__ || Object.getPrototypeOf(WatermarksPatch)).call(this));
  546. }
  547.  
  548. _createClass(WatermarksPatch, [{
  549. key: '_apply',
  550. value: function _apply() {
  551. Hooker.hookLogo(function (exports) {
  552. exports.default.prototype.reset = function () {};
  553. });
  554. }
  555. }]);
  556.  
  557. return WatermarksPatch;
  558. }(Patch);
  559.  
  560. var VipPatch = function (_Patch3) {
  561. _inherits(VipPatch, _Patch3);
  562.  
  563. function VipPatch() {
  564. _classCallCheck(this, VipPatch);
  565.  
  566. return _possibleConstructorReturn(this, (VipPatch.__proto__ || Object.getPrototypeOf(VipPatch)).call(this));
  567. }
  568.  
  569. _createClass(VipPatch, [{
  570. key: '_apply',
  571. value: function _apply() {
  572. Hooker.hookUpsOnComplete(function (res) {
  573. var data = res.data;
  574. if (data.user) {
  575. data.user.vip = true;
  576. } else {
  577. data.user = { vip: true };
  578. }
  579. });
  580. }
  581. }]);
  582.  
  583. return VipPatch;
  584. }(Patch);
  585.  
  586. var QualitySettingPatch = function (_Patch4) {
  587. _inherits(QualitySettingPatch, _Patch4);
  588.  
  589. function QualitySettingPatch() {
  590. _classCallCheck(this, QualitySettingPatch);
  591.  
  592. return _possibleConstructorReturn(this, (QualitySettingPatch.__proto__ || Object.getPrototypeOf(QualitySettingPatch)).call(this));
  593. }
  594.  
  595. _createClass(QualitySettingPatch, [{
  596. key: '_apply',
  597. value: function _apply() {
  598. this._patchPreferQuality();
  599. this._patchCurrentQuality();
  600. this._addStyle();
  601. }
  602. }, {
  603. key: '_patchPreferQuality',
  604. value: function _patchPreferQuality() {
  605. Hooker.hookSetting(function (exports) {
  606. var html = exports.default.prototype.render();
  607. var autoRe = /<div\s+data-val="auto"[^<>]*>自动<\/div>/;
  608. var sdRe = /<div\s+data-val="320p"[^<>]*>标清<\/div>/;
  609. var autoDiv = autoRe.exec(html)[0];
  610. var fhdDiv = autoDiv.replace('auto', '1080p').replace('自动', '1080p');
  611. html = html.replace(autoRe, fhdDiv).replace(sdRe, '$&' + autoDiv);
  612. exports.default.prototype.render = function () {
  613. return html;
  614. };
  615. });
  616. }
  617. }, {
  618. key: '_patchCurrentQuality',
  619. value: function _patchCurrentQuality() {
  620. Hooker.hookSetting(function (exports) {
  621. var _findRecentAvaliableQuality = exports.default.prototype._findRecentAvaliableQuality;
  622. exports.default.prototype._findRecentAvaliableQuality = function (code, qualitys) {
  623. qualitys.reverse();
  624. return _findRecentAvaliableQuality.apply(this, [code, qualitys]);
  625. };
  626. });
  627.  
  628. Hooker.hookRenderQulaity(function (qualitys) {
  629. qualitys.reverse();
  630. var idx = qualitys.findIndex(function (i) {
  631. return i.code === '1080p';
  632. });
  633. if (idx !== -1) qualitys[idx].name = '1080p';
  634. });
  635. }
  636. }, {
  637. key: '_addStyle',
  638. value: function _addStyle() {
  639. GM_addStyle('\n .personalise-layer {\n width: 315px !important;\n }\n .setting-bar.setting-confirm {\n justify-content: center !important;\n }\n ');
  640. }
  641. }]);
  642.  
  643. return QualitySettingPatch;
  644. }(Patch);
  645.  
  646. var QualityFallbackPatch = function (_Patch5) {
  647. _inherits(QualityFallbackPatch, _Patch5);
  648.  
  649. function QualityFallbackPatch() {
  650. _classCallCheck(this, QualityFallbackPatch);
  651.  
  652. return _possibleConstructorReturn(this, (QualityFallbackPatch.__proto__ || Object.getPrototypeOf(QualityFallbackPatch)).call(this));
  653. }
  654.  
  655. _createClass(QualityFallbackPatch, [{
  656. key: '_apply',
  657. value: function _apply() {
  658. Hooker.hookRenderQulaity(function (qualitys, that) {
  659. return that.data.quality = that.data.preferQuality;
  660. }); // 由优先画质决定当前画质
  661. Hooker.hookSetCurrentQuality(function (that) {
  662. return that._video.global.config.quality = that.data.quality;
  663. }); // 更新config当前画质
  664. }
  665. }]);
  666.  
  667. return QualityFallbackPatch;
  668. }(Patch);
  669.  
  670. var DashboardPatch = function (_Patch6) {
  671. _inherits(DashboardPatch, _Patch6);
  672.  
  673. function DashboardPatch() {
  674. _classCallCheck(this, DashboardPatch);
  675.  
  676. return _possibleConstructorReturn(this, (DashboardPatch.__proto__ || Object.getPrototypeOf(DashboardPatch)).call(this));
  677. }
  678.  
  679. _createClass(DashboardPatch, [{
  680. key: '_apply',
  681. value: function _apply() {
  682. this._prepare();
  683. this._patch();
  684. }
  685. }, {
  686. key: '_prepare',
  687. value: function _prepare() {
  688. this._exposeDashboard();
  689. }
  690. }, {
  691. key: '_findVarName',
  692. value: function _findVarName(code) {
  693. return (/"dashboard"\s*,\s*(\w+)/.exec(code)[1]
  694. );
  695. }
  696. }, {
  697. key: '_exposeDashboard',
  698. value: function _exposeDashboard() {
  699. var _this17 = this;
  700.  
  701. Hooker.hookGlobal(function (code) {
  702. var varName = _this17._findVarName(code);
  703. return code.replace(/\.exports\s*=\s*(\w+)/, '$&;$1.__Dashboard=' + varName + ';');
  704. }, 'code');
  705. }
  706. }, {
  707. key: '_patch',
  708. value: function _patch() {
  709. Hooker.hookGlobal(function (exports) {
  710. exports.__Dashboard.prototype.bindAutoHide = function () {
  711. var _this18 = this;
  712.  
  713. this._parent.addEventListener('mousemove', function () {
  714. _this18._hideTimeout && clearTimeout(_this18._hideTimeout);
  715. _this18.show();
  716. if (!_this18._video._videoCore._isPause) _this18._hideTimeout = setTimeout(_this18.hide.bind(_this18), _this18._args.autoHide);
  717. });
  718. this._parent.addEventListener('mouseout', function () {
  719. if (!_this18._video._videoCore._isPause) _this18.hide();
  720. });
  721. };
  722. var show = exports.__Dashboard.prototype.show;
  723. exports.__Dashboard.prototype.show = function () {
  724. this._parent.style.cursor = '';
  725. show.apply(this);
  726. };
  727. var hide = exports.__Dashboard.prototype.hide;
  728. exports.__Dashboard.prototype.hide = function () {
  729. this._parent.style.cursor = 'none'; // 隐藏鼠标
  730. hide.apply(this);
  731. };
  732. });
  733. }
  734. }]);
  735.  
  736. return DashboardPatch;
  737. }(Patch);
  738.  
  739. var PlayerPatch = function (_Patch7) {
  740. _inherits(PlayerPatch, _Patch7);
  741.  
  742. function PlayerPatch() {
  743. _classCallCheck(this, PlayerPatch);
  744.  
  745. return _possibleConstructorReturn(this, (PlayerPatch.__proto__ || Object.getPrototypeOf(PlayerPatch)).call(this));
  746. }
  747.  
  748. _createClass(PlayerPatch, [{
  749. key: '_apply',
  750. value: function _apply() {
  751. this._prepare();
  752. this._hookPlayer();
  753. }
  754. }, {
  755. key: '_prepare',
  756. value: function _prepare() {
  757. Hooker.hookTips(function (exports) {
  758. var showHintTips = exports.default.prototype.showHintTips;
  759. exports.default.prototype.showHintTips = function (code, info) {
  760. if (info.msg) {
  761. this._hintLayer.setHintShow(info.msg);
  762. } else {
  763. showHintTips.apply(this, [code, info]);
  764. }
  765. };
  766. });
  767. Hooker.hookGlobal(function (exports) {
  768. // 单video seek 后不自动播放
  769. var _setCurrentTime = exports.SingleVideoControl.prototype._setCurrentTime;
  770. exports.SingleVideoControl.prototype._setCurrentTime = function (time) {
  771. var play = this.video.play;
  772. this.video.play = function () {};
  773. _setCurrentTime.apply(this, [time]);
  774. this.video.play = play;
  775. };
  776. });
  777. }
  778. }, {
  779. key: '_hookPlayer',
  780. value: function _hookPlayer() {
  781. Hooker.hookPlayer(this._hookPlayerCallback.bind(this));
  782. }
  783. }, {
  784. key: '_hookPlayerCallback',
  785. value: function _hookPlayerCallback(exports) {
  786. var proto = exports.default.prototype;
  787.  
  788. proto._showTip = function (msg) {
  789. this._emitter.emit('player.showinfo', { type: 'hint', msg: msg });
  790. };
  791.  
  792. proto.play = function () {
  793. this._player && this._player.control.play();
  794. this._showTip('播放');
  795. };
  796.  
  797. proto._pause = proto.pause;
  798. proto.pause = function () {
  799. this._pause();
  800. this._showTip('暂停');
  801. };
  802.  
  803. proto.adjustVolume = function (value) {
  804. this._player && this._player.control.setVolume(this.global.playerState.volume + value);
  805. };
  806.  
  807. proto.toggleMute = function () {
  808. if (this.global.playerState.muted) this._showTip('取消静音');
  809. this.setMuted(!this.global.playerState.muted);
  810. };
  811.  
  812. proto.stepSeek = function (stepTime) {
  813. var duration = this._player.control.getDuration();
  814. var currentTime = this.global.currentTime;
  815. var seekTime = Math.max(0, Math.min(duration, currentTime + stepTime));
  816. this.seek(seekTime);
  817.  
  818. var msg = void 0;
  819. if (Math.abs(stepTime) < 60) {
  820. msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime + '\u79D2' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) + '\u79D2';
  821. } else {
  822. msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime / 60 + '\u5206\u949F' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) / 60 + '\u5206\u949F';
  823. }
  824. this._showTip(msg);
  825. };
  826.  
  827. proto.rangeSeek = function (range) {
  828. var duration = this._player.control.getDuration();
  829. var seekTime = Math.max(0, Math.min(duration, duration * range));
  830. this.seek(seekTime);
  831. this._showTip('定位:' + (range * 100).toFixed(0) + '%');
  832. };
  833.  
  834. proto.isFullScreen = function () {
  835. return this.global.playerState.fullscreen;
  836. };
  837.  
  838. proto.toggleFullScreen = function () {
  839. if (this.isFullScreen()) {
  840. this.exitFullscreen();
  841. } else {
  842. this.fullScreen();
  843. }
  844. };
  845.  
  846. proto.adjustPlaybackRate = function (value) {
  847. var videoCore = this._player.control._videoCore;
  848. var rate = Math.max(0.2, Math.min(5, videoCore.video.playbackRate + value));
  849. if (this._player.config.controlType === 'multi') {
  850. videoCore._videoElments.forEach(function (v) {
  851. return v.playbackRate = rate;
  852. });
  853. } else {
  854. videoCore.video.playbackRate = rate;
  855. }
  856. this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate.toFixed(1).replace(/\.0+$/, ''));
  857. };
  858.  
  859. proto.resetPlaybackRate = function () {
  860. this._player.control.setRate(1);
  861. this._showTip('恢复播放速率');
  862. };
  863.  
  864. proto.getFps = function () {
  865. return 25; // 标清fps为15,标清以上fps为25。
  866. };
  867.  
  868. proto.prevFrame = function () {
  869. var state = this.global.playerState.state;
  870. if (state === 'playing') this.pause();
  871. var duration = this._player.control.getDuration();
  872. var currentTime = this.global.currentTime;
  873. var seekTime = Math.max(0, Math.min(duration, currentTime - 1 / this.getFps()));
  874. this.seek(seekTime);
  875. this._showTip('上一帧');
  876. };
  877.  
  878. proto.nextFrame = function () {
  879. var state = this.global.playerState.state;
  880. if (state === 'playing') this.pause();
  881. var duration = this._player.control.getDuration();
  882. var currentTime = this.global.currentTime;
  883. var seekTime = Math.max(0, Math.min(duration, currentTime + 1 / this.getFps()));
  884. this.seek(seekTime);
  885. this._showTip('下一帧');
  886. };
  887.  
  888. proto.playPrev = function () {
  889. // TODO:
  890. };
  891.  
  892. proto.playNext = function () {
  893. // TODO:
  894. };
  895. }
  896. }]);
  897.  
  898. return PlayerPatch;
  899. }(Patch);
  900.  
  901. var playerPatch = new PlayerPatch();
  902.  
  903. var KeyShortcutsPatch = function (_Patch8) {
  904. _inherits(KeyShortcutsPatch, _Patch8);
  905.  
  906. function KeyShortcutsPatch() {
  907. _classCallCheck(this, KeyShortcutsPatch);
  908.  
  909. return _possibleConstructorReturn(this, (KeyShortcutsPatch.__proto__ || Object.getPrototypeOf(KeyShortcutsPatch)).call(this));
  910. }
  911.  
  912. _createClass(KeyShortcutsPatch, [{
  913. key: '_apply',
  914. value: function _apply() {
  915. this._prepare();
  916. this._addListener();
  917. }
  918. }, {
  919. key: '_prepare',
  920. value: function _prepare() {
  921. playerPatch.install();
  922. this._obtainPlayer();
  923. }
  924. }, {
  925. key: '_obtainPlayer',
  926. value: function _obtainPlayer() {
  927. var self = this;
  928. Hooker.hookKeyShortcuts(function (exports) {
  929. exports.default.prototype.registerEvents = function () {
  930. self._player = this._player;
  931. };
  932. });
  933. }
  934. }, {
  935. key: '_addListener',
  936. value: function _addListener() {
  937. document.addEventListener('keydown', this._handler.bind(this));
  938. }
  939. }, {
  940. key: '_handler',
  941. value: function _handler(event) {
  942. if (event.target.nodeName !== 'BODY') return;
  943.  
  944. switch (event.keyCode) {
  945. case 32:
  946. // Spacebar
  947. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  948. var state = this._player.global.playerState.state;
  949. if (state === 'paused' || state === 'ended' || state === 'player.init') {
  950. this._player.play();
  951. } else {
  952. this._player.pause();
  953. }
  954. } else {
  955. return;
  956. }
  957. break;
  958. case 39: // → Arrow Right
  959. case 37:
  960. {
  961. // ← Arrow Left
  962. var stepTime = void 0;
  963. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  964. stepTime = 39 === event.keyCode ? 5 : -5;
  965. } else if (event.ctrlKey && !event.shiftKey && !event.altKey) {
  966. stepTime = 39 === event.keyCode ? 30 : -30;
  967. } else if (!event.ctrlKey && event.shiftKey && !event.altKey) {
  968. stepTime = 39 === event.keyCode ? 60 : -60;
  969. } else if (event.ctrlKey && !event.shiftKey && event.altKey) {
  970. stepTime = 39 === event.keyCode ? 3e2 : -3e2; // 5分钟
  971. } else {
  972. return;
  973. }
  974. this._player.stepSeek(stepTime);
  975. break;
  976. }
  977. case 38: // ↑ Arrow Up
  978. case 40:
  979. // ↓ Arrow Down
  980. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  981. this._player.adjustVolume(38 === event.keyCode ? 0.05 : -0.05);
  982. } else {
  983. return;
  984. }
  985. break;
  986. case 77:
  987. // M
  988. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  989. this._player.toggleMute();
  990. } else {
  991. return;
  992. }
  993. break;
  994. case 13:
  995. // Enter
  996. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  997. this._player.toggleFullScreen();
  998. } else {
  999. return;
  1000. }
  1001. break;
  1002. case 67: // C
  1003. case 88:
  1004. // X
  1005. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1006. this._player.adjustPlaybackRate(67 === event.keyCode ? 0.1 : -0.1);
  1007. } else {
  1008. return;
  1009. }
  1010. break;
  1011. case 90:
  1012. // Z
  1013. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1014. this._player.resetPlaybackRate();
  1015. } else {
  1016. return;
  1017. }
  1018. break;
  1019. case 68: // D
  1020. case 70:
  1021. // F
  1022. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1023. if (event.keyCode === 68) {
  1024. this._player.prevFrame();
  1025. } else {
  1026. this._player.nextFrame();
  1027. }
  1028. } else {
  1029. return;
  1030. }
  1031. break;
  1032. case 80: // P
  1033. case 78:
  1034. // N
  1035. if (!event.ctrlKey && event.shiftKey && !event.altKey) {
  1036. if (event.keyCode === 78) {
  1037. this._player.playNext();
  1038. } else {
  1039. this._player.playPrev();
  1040. }
  1041. } else {
  1042. return;
  1043. }
  1044. break;
  1045. default:
  1046. if (event.keyCode >= 48 && event.keyCode <= 57) {
  1047. // 0 ~ 9
  1048. if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
  1049. this._player.rangeSeek((event.keyCode - 48) * 0.1);
  1050. } else {
  1051. return;
  1052. }
  1053. } else {
  1054. return;
  1055. }
  1056. }
  1057.  
  1058. event.preventDefault();
  1059. event.stopPropagation();
  1060. }
  1061. }]);
  1062.  
  1063. return KeyShortcutsPatch;
  1064. }(Patch);
  1065.  
  1066. var MouseShortcutsPatch = function (_Patch9) {
  1067. _inherits(MouseShortcutsPatch, _Patch9);
  1068.  
  1069. function MouseShortcutsPatch() {
  1070. _classCallCheck(this, MouseShortcutsPatch);
  1071.  
  1072. return _possibleConstructorReturn(this, (MouseShortcutsPatch.__proto__ || Object.getPrototypeOf(MouseShortcutsPatch)).call(this));
  1073. }
  1074.  
  1075. _createClass(MouseShortcutsPatch, [{
  1076. key: '_apply',
  1077. value: function _apply() {
  1078. this._prepare();
  1079. this._addListener();
  1080. }
  1081. }, {
  1082. key: '_prepare',
  1083. value: function _prepare() {
  1084. playerPatch.install();
  1085. }
  1086. }, {
  1087. key: '_addListener',
  1088. value: function _addListener() {
  1089. Hooker.hookPlayerInitServiceEvent(function (that) {
  1090. var timer = void 0;
  1091. that.container.addEventListener('click', function (event) {
  1092. if (event.target.className !== 'h5-ext-layer-adsdk') return;
  1093. if (timer) {
  1094. clearTimeout(timer);
  1095. timer = null;
  1096. return;
  1097. }
  1098. timer = setTimeout(function () {
  1099. var state = that.global.playerState.state;
  1100. if (state === 'paused' || state === 'ended' || state === 'player.init') {
  1101. that.play();
  1102. } else {
  1103. that.pause();
  1104. }
  1105. timer = null;
  1106. }, 200);
  1107. });
  1108. that.container.addEventListener('dblclick', function () {
  1109. return that.toggleFullScreen();
  1110. });
  1111. that.container.addEventListener('wheel', function (event) {
  1112. if (!that.isFullScreen()) return;
  1113. var delta = event.wheelDelta || event.detail || event.deltaY && -event.deltaY;
  1114. that.adjustVolume(delta > 0 ? 0.05 : -0.05);
  1115. });
  1116. });
  1117. }
  1118. }]);
  1119.  
  1120. return MouseShortcutsPatch;
  1121. }(Patch);
  1122.  
  1123. var ShortcutsPatch = function (_Patch10) {
  1124. _inherits(ShortcutsPatch, _Patch10);
  1125.  
  1126. function ShortcutsPatch() {
  1127. _classCallCheck(this, ShortcutsPatch);
  1128.  
  1129. return _possibleConstructorReturn(this, (ShortcutsPatch.__proto__ || Object.getPrototypeOf(ShortcutsPatch)).call(this));
  1130. }
  1131.  
  1132. _createClass(ShortcutsPatch, [{
  1133. key: '_apply',
  1134. value: function _apply() {
  1135. new KeyShortcutsPatch().install();
  1136. Logger.log('添加键盘快捷键');
  1137. new MouseShortcutsPatch().install();
  1138. Logger.log('添加鼠标快捷键');
  1139. }
  1140. }]);
  1141.  
  1142. return ShortcutsPatch;
  1143. }(Patch);
  1144.  
  1145. var H5Patch = function (_Patch11) {
  1146. _inherits(H5Patch, _Patch11);
  1147.  
  1148. function H5Patch() {
  1149. _classCallCheck(this, H5Patch);
  1150.  
  1151. return _possibleConstructorReturn(this, (H5Patch.__proto__ || Object.getPrototypeOf(H5Patch)).call(this));
  1152. }
  1153.  
  1154. _createClass(H5Patch, [{
  1155. key: '_apply',
  1156. value: function _apply() {
  1157. Hooker.hookDefine('page/find/play/player/load', this._forceH5.bind(this));
  1158. }
  1159. }, {
  1160. key: '_forceH5',
  1161. value: function _forceH5(code) {
  1162. return code.replace(/(if\s*\().*?(\)\s*\{)/, '$1true$2');
  1163. }
  1164. }]);
  1165.  
  1166. return H5Patch;
  1167. }(Patch);
  1168.  
  1169. function enableH5Player() {
  1170. new H5Patch().install();
  1171. Logger.log('启用html5播放器');
  1172. }
  1173.  
  1174. function blockAds() {
  1175. new AdBlockPatch().install();
  1176. Logger.log('和谐广告');
  1177. }
  1178.  
  1179. function invalidateWatermarks() {
  1180. new WatermarksPatch().install();
  1181. Logger.log('和谐水印');
  1182. }
  1183.  
  1184. function invalidateQualityLimitation() {
  1185. new VipPatch().install();
  1186. Logger.log('解除会员画质限制');
  1187. }
  1188.  
  1189. function improveQualitySetting() {
  1190. new QualitySettingPatch().install();
  1191. Logger.log('设置里优先画质增加1080P选项并与当前画质对齐');
  1192. }
  1193.  
  1194. function improveQualityFallback() {
  1195. new QualityFallbackPatch().install();
  1196. Logger.log('改善当前画质逻辑');
  1197. }
  1198.  
  1199. function improveAutoHide() {
  1200. new DashboardPatch().install();
  1201. Logger.log('改善控件与光标自动隐藏');
  1202. }
  1203.  
  1204. function improveShortcuts() {
  1205. new ShortcutsPatch().install();
  1206. }
  1207.  
  1208. //=============================================================================
  1209.  
  1210. enableH5Player();
  1211. blockAds();
  1212. invalidateWatermarks();
  1213. invalidateQualityLimitation();
  1214. improveQualitySetting();
  1215. improveQualityFallback();
  1216. improveAutoHide();
  1217. improveShortcuts();
  1218. })();