视频v3-自用-自动解析

无需跳转新网址,打开官网直接看,如有侵权请联系作者删除

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

  1. // ==UserScript==
  2. // @name 视频v3-自用-自动解析
  3. // @namespace https://www.tampermonkey.net/
  4. // @version 1.0.4
  5. // @license AGPL-3.0
  6. // @description 无需跳转新网址,打开官网直接看,如有侵权请联系作者删除
  7. // @author Tenfond
  8. // @match *
  9. // @include *
  10. // @grant none
  11. // @run-at document-body
  12. // ==/UserScript==
  13. /**
  14. * 任务清单:
  15. * 解析源更换优化,无推荐时,使用备用解析源
  16. * 更新 仅解析VIP 功能
  17. */
  18.  
  19. // 有任何问题都可以联系我邮箱 tenfond@outlook.com
  20.  
  21. // 读取配置后执行
  22. function readSettings() {
  23. // 获取框架循环时间,CPU性能好的可以设置为100,CPU性能不好的可以设置为1000
  24. settings.getElementTimes = 500;
  25. // log输出字体布局
  26. settings.fontStyle = {
  27. error: "font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; color: #f00;",
  28. warn: "font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; color: #ff0;",
  29. ok: "font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; color: #0f0;",
  30. maxTip: "font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; font-size: 30px; background-color: #222; text-shadow: 0px 0px 12px #fff; color: #fff;"
  31. };
  32.  
  33. if (window === top) {
  34. /*
  35. * (): 小括号括住的表示推荐解析 画质高 速度快
  36. * : 无括号的表示视频带水印 或 原页面画质
  37. * []: 方括号表示标清画质 不推荐
  38. */
  39. settings.NoAD解析 = { // TODO by 17kyun.com/api.php?url= // TODO by tv.hzwdd.cn
  40. // 你可以在这里定义自己的解析接口,脚本会自动适配。格式如下:
  41. // "解析名称": "解析接口的链接", // TODO 注意 : 和 " 以及 , 都是英文的符号。
  42. "B站": "https://vip.parwix.com:4433/player/?url=", // TODO 腾讯 (芒果)
  43. "OK解析": "https://api.okjx.cc:3389/jx.php?url=" || "https://okjx.cc/?url=" || "https://m2090.com/?url=" // TODO 优质: 腾讯 (爱奇艺) 优酷 乐视 芒果 PPTV (华数)
  44. };
  45. settings.AD解析 = { // TODO (有赌博广告,请勿相信,这么简单的骗术不会有人上当吧)
  46. "CKmov解析": "https://www.ckmov.vip/api.php?url=",
  47. "CK解析": "https://www.ckplayer.vip/jiexi/?url=" // TODO (B站)
  48. };
  49. start();
  50. } else if (settings.isParse) {
  51. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00给予\x000\x00" + location.href, settings.k1, settings.k2), "*");
  52. Object.defineProperty(console, "clear", {
  53. value: () => console.log("%c禁止清除控制台", settings.fontStyle.error), writable: false
  54. });
  55. settings.parseDB = new Promise(resolve => {
  56. window.addEventListener("message", event => {
  57. if (event.source !== window) {
  58. try {
  59. let sql = key.DECRYPT(event.data, settings.k1, settings.k2).split("\x00");
  60. if (sql[0] === "天王盖地虎") {
  61. if (sql[1] === "给予") {
  62. if (sql[2] === "用户数据库") {
  63. resolve(JSON.parse(sql[3]));
  64. }
  65. }
  66. }
  67. } catch (e) {
  68. // 排除 下标越界错误 及 指令处理错误
  69. }
  70. }
  71. });
  72. });
  73. // 需要先监听再发送数据
  74. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00请求\x00用户数据库", settings.k1, settings.k2), "*");
  75. start();
  76. }
  77. }
  78.  
  79. // 未经许可禁止抄袭算法,可以私用。
  80. const key = (() => {
  81. // 新方案定义私有变量。修复部分浏览器不支持 # 定义private私有变量
  82. const password = Symbol();
  83. const randomkey = Symbol();
  84.  
  85. // 自定义加密算法,以防数据包被破解。
  86. class key {
  87. // _pwd; // 火狐v68版本貌似不支持这种方式声明变量。
  88.  
  89. constructor(pwd = null) {
  90. // num,密码偏移量
  91. // key,排列长度偏移量
  92. // charCode,防止内存频繁运动,定义在外部
  93. let num = 7, charCode, key = 7;
  94. if (pwd) {
  95. if (typeof pwd === "string") {
  96. for (let i = 0; i < pwd.length; i++) {
  97. // 将pwd中 每个字 转换成 十进制ASCII值
  98. charCode = pwd[i].charCodeAt();
  99. // 将每个 ASCII值 中 第一个值加入到 排列长度偏移量
  100. key += parseInt(charCode.toString()[0]);
  101. // 用 hash算法 将 ASCII值 减去 31 作为新的值加入到num中
  102. // 以下方法是为了防止出现负数,ASCII字符集一共有65536个字符
  103. // num += charCode - 31 => (charCode + 65505) % 65536
  104. num = 31 * num + (charCode + 65505) % 65536;
  105. }
  106. } else if (typeof pwd === "number") {
  107. // 如果密码是数值型就使用此方法作为 密码偏移量 和 排列长度偏移量
  108. num = key = 7 + parseInt(Math.abs(pwd));
  109. } else {
  110. // 如果类型不匹配就直接提出错误
  111. console.error("Unsupported type '" + (typeof pwd) + "'. It only supports 'string' or 'numbers'.")
  112. }
  113. }
  114. // 让排列长度偏移量的转换成8进制,取第一个数字。加上密码转换成字符字符串的方式。数值+字符串 会将数值自动转换为字符串
  115. this[password] = key.toString(8)[0] + (num % 65536).toString();
  116. }
  117.  
  118. encrypt(string) {
  119. if (string) {
  120. // subStart 排列长度的起始位置。subIndex 排列长度。 encryptPool 加密池,即去除的排列长度存放在这里。result 加密后的结果。
  121. let subStart = string.length, subIndex = parseInt(this[password][0]) + 3, encryptPool = [], result = "";
  122. // stringKey 加密字符偏移量的散列值的的个数。
  123. let stringKey = subStart + parseInt(this[password].substring(1));
  124. // stringKeyFloat 加密字符偏移量的偏移单位。stringKeyIndex 加密字符偏移量的位置
  125. let stringKeyFloat = 65536 / stringKey, stringKeyIndex = stringKey - 1;
  126. // 获取加密池。
  127. while (subStart > subIndex) {
  128. subStart -= subIndex;
  129. encryptPool.push(string.substr(subStart, subIndex));
  130. }
  131. encryptPool.push(string.substring(0, subStart));
  132. // 对加密池进行加密,并将加密的字符的结果放入 result 中。
  133. for (let i = 0, j; i < subIndex; i++) {
  134. for (j = 0; j < encryptPool.length; j++) {
  135. let char = encryptPool[j][i];
  136. if (char) {
  137. // 将字符的 ASCII值 偏移 指定量
  138. result += String.fromCharCode((char.charCodeAt() + parseInt(stringKeyFloat * (stringKeyIndex % 2 === 0 ? stringKeyIndex : stringKey - stringKeyIndex))) % 65536);
  139. stringKeyIndex = stringKeyIndex === 0 ? stringKey - 1 : stringKeyIndex - 1;
  140. } else {
  141. break;
  142. }
  143. }
  144. }
  145. // 返回加密结果
  146. return result;
  147. } else {
  148. // 如果加密字符串不存在就返回空字符串
  149. return "";
  150. }
  151. }
  152.  
  153. /* 假设有7个字符
  154.  
  155. 加密前 - 排列
  156. ( 1 ) ( 2 3 ) ( 4 5 ) ( 6 7 )
  157.  
  158. 加密中 - 排列
  159. ︵ ︵ ︵ ︵
  160. 6 4 2 1
  161. 7 5 3 ︶
  162. ︶ ︶ ︶
  163. 加密后 - 排列
  164. ( 6 4 2 1 ) ( 7 5 3 )
  165.  
  166. 解密中 - 排列
  167. ︵ ︵
  168. 6 7
  169. 4 5
  170. 2 3
  171. 1 ︶
  172. 解密后 - 排列
  173. 1 2 3 4 5 6 7 8
  174. */
  175.  
  176. decrypt(string) {
  177. if (string) {
  178. // subStart 排列长度的起始位置。desubIndex 反向取加密池的长度。 decryptPool 解密池。
  179. let subStart = 0, desubIndex = Math.ceil(string.length / (parseInt(this[password][0]) + 3)),
  180. //NullCount 加密池中最后一个元素的元素空位。 desubIndex 反向取加密池的长度。 decryptPool 解密池,result 解密后的结果。
  181. NullCount = string.length % (parseInt(this[password][0]) + 3), decryptPool = [], result = "";
  182. // stringKey 加密字符偏移量的散列值的的个数。
  183. let stringKey = string.length + parseInt(this[password].substring(1)), // stringKeyFloat 加密字符偏移量的偏移单位。stringKeyIndex 加密字符偏移量的位置
  184. stringKeyFloat = 65536 / stringKey, stringKeyIndex;
  185. // 获取解密池
  186. while (string.length - subStart > desubIndex) {
  187. decryptPool.push(string.substr(subStart, desubIndex));
  188. subStart += desubIndex;
  189. if (decryptPool.length === NullCount) {
  190. desubIndex--;
  191. }
  192. }
  193. decryptPool.push(string.substring(subStart));
  194. // 对解密池进行解密 并将解密结果 加入到 result(结果) 中
  195. for (let j = decryptPool[0].length - 1, i; j > -1; j--) {
  196. // 为节省NullCount的空间利用,使用NullCount用来辅助计算 stringKeyIndex(加密字符偏移量的位置) 的位置
  197. // 画图排列就知道为什么要这样做了,上面做了一个加密到解密的排列的草图
  198. NullCount = 0;
  199. for (i = 0; i < decryptPool.length; i++) {
  200. let char = decryptPool[i][j];
  201. if (char) {
  202. NullCount += decryptPool[i].length;
  203. // 计算得到当前字符的位置
  204. stringKeyIndex = NullCount - decryptPool[i].length + j + 1;
  205. // 计算得到 stringKeyIndex(加密字符偏移量的位置) 的位置
  206. stringKeyIndex = (stringKey - stringKeyIndex % stringKey) % stringKey;
  207. // 让加密后的偏移量,偏移回去,得到原先的字符串
  208. result += String.fromCharCode((char.charCodeAt() - parseInt(stringKeyFloat * (stringKeyIndex % 2 === 0 ? stringKeyIndex : stringKey - stringKeyIndex)) + 65536) % 65536);
  209. }
  210. }
  211. }
  212. // 返回解密结果
  213. return result;
  214. } else {
  215. // 如果解密字符串不存在就返回空字符串
  216. return "";
  217. }
  218. }
  219.  
  220. // encrypt 既可以用作加密 也可以用作解密,decrypt 既可以用作解密 也可以用作加密。
  221.  
  222. static ENCRYPT() {
  223. if (arguments) {
  224. let strings = [], keys = [];
  225. for (let i = 0; i < arguments.length; i++) {
  226. // JavaScript如何用最简单的方法获取任意对象的类名?(包括自定义类) 判断对象类型?
  227. // 欢迎支持我的原创文档 https://blog.csdn.net/qq_37759464/article/details/121764755
  228. if (arguments[i].constructor.name === "key") {
  229. keys.push(arguments[i]);
  230. } else if (arguments[i].constructor.name === "String") {
  231. strings.push(arguments[i]);
  232. }
  233. }
  234. if (strings) {
  235. if (keys) {
  236. for (let i = 0, j; i < strings.length; i++) {
  237. for (j = 0; j < keys.length; j++) {
  238. strings[i] = i % 2 === 0 ? keys[j].encrypt(strings[i]) : keys[j].decrypt(strings[i]);
  239. }
  240. }
  241. return strings.length === 1 ? strings[0] : strings;
  242. } else {
  243. if (!this[randomkey]) {
  244. this[randomkey] = new key(parseInt(Math.random() * 1024) + 3);
  245. }
  246. // 为了使加密方法不一样,这里反过来
  247. strings[i] = this[randomkey].decrypt(this[randomkey].decrypt(strings[i]));
  248. return strings.length === 1 ? strings[0] : strings;
  249. }
  250. }
  251. }
  252. }
  253.  
  254. static DECRYPT() {
  255. if (arguments) {
  256. let strings = [], keys = [];
  257. for (let i = 0; i < arguments.length; i++) {
  258. if (arguments[i].constructor.name === "key") {
  259. keys.push(arguments[i]);
  260. } else if (arguments[i].constructor.name === "String") {
  261. strings.push(arguments[i]);
  262. }
  263. }
  264. if (strings) {
  265. if (keys) {
  266. for (let i = 0, j; i < strings.length; i++) {
  267. for (j = keys.length - 1; j > -1; j--) {
  268. strings[i] = i % 2 === 0 ? keys[j].decrypt(strings[i]) : keys[j].encrypt(strings[i]);
  269. }
  270. }
  271. return strings.length === 1 ? strings[0] : strings;
  272. } else {
  273. if (!this[randomkey]) {
  274. this[randomkey] = new key(parseInt(Math.random() * 1024) + 3);
  275. }
  276. strings[i] = this[randomkey].encrypt(this[randomkey].encrypt(strings[i]));
  277. return strings.length === 1 ? strings[0] : strings;
  278. }
  279. }
  280. }
  281. }
  282. }
  283.  
  284. return key;
  285. })();
  286.  
  287. if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i)) {
  288. // 修改手机端UA,似乎改完这个UA还是没有效果。说明苹果端页面从数据请求就开始检测UA了。请手动修改浏览器UA。
  289. Object.defineProperty(navigator, 'userAgent', {
  290. // 这个UA会屏蔽百度搜索的广告?
  291. value: "Mozilla/5.0 (Linux; Android 8.0; MI 6 Build/OPR1.170623.027; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/48.0.2564.116 Mobile Safari/537.36 T7/10.3 SearchCraft/2.6.3 (Baidu; P1 8.0.0)",
  292. writable: false
  293. });
  294. }
  295. let settings = {};
  296. const root = document.querySelector(":root");
  297. (() => {
  298. if (location.search.match(/[?&]url=https?:\/\/.+\..+\..+\/.+/i) ||
  299. location.search.match(/[?&]v=https?:\/\/.+\..+\..+\/.+/i) ||
  300. location.href.match(/https?:\/\/api\.leduotv\.com\/.+?vid=/i)) {
  301. settings.isParse = true;
  302. }
  303. if (settings.isParse || location.host.indexOf("v.qq.com") !== -1 || location.host.indexOf("iqiyi.com") !== -1 || location.host.indexOf("youku.com") !== -1 || location.host.indexOf("bilibili.com") !== -1 || location.host.indexOf("miguvideo.com") !== -1 || location.host.indexOf("le.com") !== -1 || location.host.indexOf("tv.sohu.com") !== -1 || location.host.indexOf("film.sohu.com") !== -1 || location.host.indexOf("mgtv.com") !== -1 || location.host.indexOf("ixigua.com") !== -1 || location.host.indexOf("pptv.com") !== -1 || location.host.indexOf("vip.1905.com") !== -1 || location.host.indexOf("www.wasu.com") !== -1) {
  304. // 对符合条件的域名执行脚本
  305. // 调用自写加密算法,生成实例类
  306. settings.k1 = new key("Tenfond");
  307. settings.k2 = new key(" 腾 风 ");
  308. if (window === top) {
  309. settings.parseDB = {
  310. 解析开关: "\x01", 弹幕开关: "\x01", DIY解析栏: "\x01"
  311. };
  312. for (let name in settings.parseDB) {
  313. let data = localStorage.getItem("解析数据库." + name);
  314. if (data !== null) {
  315. settings.parseDB[name] = data;
  316. }
  317. }
  318. if (settings.parseDB.解析开关) {
  319. if (!sessionStorage.getItem("tip设置")) {
  320. showTip("右下角可以编辑 设置");
  321. sessionStorage.setItem("tip设置", "\x01");
  322. }
  323. readSettings();
  324. }
  325. settings.parseDBFuntions = {
  326. 解析开关: () => {
  327. if (!settings.parseDB.解析开关) {
  328. location.reload();
  329. // window 刷新时会自动清除缓存
  330. } else {
  331. readSettings();
  332. settings.parseDB.解析开关 = "\x01";
  333. }
  334. }, 弹幕开关: () => showTip("刷新页面即可生效"), DIY解析栏: () => {
  335. if (typeof settings.DIY_iframeFunction === "function") {
  336. settings.DIY_iframeFunction();
  337. } else {
  338. showTip("设置已生效");
  339. }
  340. }
  341. };
  342. let toolsBar = document.createElement("toolsbar");
  343. toolsBar.style = "display: block !important; visibility: visible !important; position: fixed; z-index: 2147483647 !important; left:0; bottom: 0; width: 100%; height: 0; font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; font-size: 15px; color: #000;";
  344. toolsBar.innerHTML = "<style>\n" +
  345. " text{font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; font-size: 15px; color: #000; position: absolute; transform: translateY(-50%); top: 50%;}\n" +
  346. " label.parse-switch{position: absolute; transform: translateY(-50%); top: 50%; display: inline-block; width: 44px; height: 24px; box-shadow: 0 0 0 1px #ccc; border-radius: 30px; overflow: hidden;}\n" +
  347. " label.parse-switch>input[type=checkbox]{display: none;}\n" +
  348. " label.parse-switch>input[type=checkbox]+bg{position: absolute; transition: background-color 0.3s; background-color: #ccc; width: 100%; height: 100%;}\n" +
  349. " label.parse-switch>input[type=checkbox]:checked+bg{background-color: #4af}\n" +
  350. " label.parse-switch>input[type=checkbox]+bg+span{position: absolute; transition: left 0.3s; left: 0; width: 24px; height: 24px; border-radius: 50%; background-color: #fff;}\n" +
  351. " label.parse-switch>input[type=checkbox]:checked+bg+span{left: 20px}\n" + "\n" +
  352. " settings>button+ul>li{position: relative; background-color: #0000; width: 100%; height: 30px;}\n" +
  353. "</style>\n" + "<settings style='box-shadow: 0 0 6px 2px #444; position: fixed; width: 50px; height: 30px; right: 7%; bottom: 45px; border-radius: 15px;'>" +
  354. " <button style='width: 100%; height: 100%; border-radius: 17px; background-color: #4af; border-color: #4af; text-align: center; color: #fff;'>\n" +
  355. " 设置\n" +
  356. " </button>\n" +
  357. " <ul style='position:absolute; transition: all 0.5s; right: 7%; bottom: 100%; opacity: 0; width: 0; height: auto; background-color: #fffc; border: 1px solid #ccc; border-radius: 5px;'>\n" +
  358. " </ul>\n" +
  359. "</settings>";
  360. let SettingsBlock = toolsBar.querySelector("settings>button+ul");
  361. let parseDBKeys = Object.keys(settings.parseDB);
  362. for (let i = 0; i < parseDBKeys.length; i++) {
  363. SettingsBlock.innerHTML += "<li><text style='left: 10px'>" + parseDBKeys[i] + "</text><label class='parse-switch' style='right: 10px;'><input type='checkbox'><bg></bg><span></span></label></li>\n";
  364. }
  365. let SettingBlockSwitchs = SettingsBlock.querySelectorAll("li>label.parse-switch");
  366. for (let i = 0; i < SettingBlockSwitchs.length; i++) {
  367. let checkBox = SettingBlockSwitchs[i].querySelector("input[type=checkbox]");
  368. checkBox.checked = Boolean(settings.parseDB[parseDBKeys[i]]);
  369. SettingBlockSwitchs[i].querySelector("bg").addEventListener("transitionend", () => {
  370. if (checkBox.checked !== Boolean(settings.parseDB[parseDBKeys[i]])) {
  371. // 如果有变化才会执行,否则会重复执行,因为动画会有延迟,刚打开网页时也会出发此监听事件
  372. if (checkBox.checked) {
  373. settings.parseDB[parseDBKeys[i]] = "\x01";
  374. } else {
  375. settings.parseDB[parseDBKeys[i]] = "";
  376. }
  377. localStorage.setItem("解析数据库." + parseDBKeys[i], settings.parseDB[parseDBKeys[i]]);
  378. settings.parseDBFuntions[parseDBKeys[i]]();
  379. }
  380. }, false);
  381. }
  382. let SettingsBtn = toolsBar.querySelector("settings>button");
  383. SettingsBtn.onclick = () => {
  384. if (SettingsBlock.style.opacity === "0") {
  385. SettingsBtn.innerText = "关闭";
  386. SettingsBlock.style.opacity = "1";
  387. SettingsBlock.style.width = "200px";
  388. } else {
  389. SettingsBtn.innerText = "设置";
  390. SettingsBlock.style.opacity = "0";
  391. SettingsBlock.style.width = "0";
  392. }
  393. }
  394. root.append(toolsBar);
  395. } else {
  396. readSettings();
  397. }
  398. }
  399. })();
  400.  
  401. function start() {
  402. console.log("脚本运行在 " + location.href);
  403.  
  404. function detectMobile() {
  405. return (navigator.userAgent.match(/Android/i) ||
  406. navigator.userAgent.match(/webOS/i) ||
  407. navigator.userAgent.match(/Windows Phone/i) ||
  408. navigator.userAgent.match(/Symbian/i) ||
  409. navigator.userAgent.match(/BlackBerry/i) ||
  410. navigator.userAgent.match(/hpwOS/i));
  411. }
  412.  
  413. function doElement(cssString, doFunction, waitMS = 0) {
  414. let Element = document.querySelector(cssString);
  415. if (Element && Element.nodeType === 1) {
  416. doFunction(Element);
  417. console.log("%c已为 " + cssString + " 进行了操作", settings.fontStyle.ok);
  418. } else if (document.readyState !== "complete" || waitMS > 0) {
  419. console.log("正在查找 " + cssString); // TODO 10毫秒约函数执行时间
  420. setTimeout(() => doElement(cssString, doFunction, document.readyState !== "complete" ? waitMS : waitMS - 10 - settings.getElementTimes), settings.getElementTimes);
  421. } else {
  422. console.log("%c未找到 " + cssString, settings.fontStyle.error);
  423. }
  424. }
  425.  
  426. function doElements(cssString, doFunction, waitMS = 0, index = 0) {
  427. let Elements = document.querySelectorAll(cssString);
  428. if (Elements[index] && Elements[index].nodeType === 1) {
  429. doFunction(Elements);
  430. console.log("%c已为 All[" + index + "] " + cssString + " 进行了操作", settings.fontStyle.ok);
  431. } else if (document.readyState !== "complete" || waitMS > 0) {
  432. console.log("正在查找 All[" + index + "] " + cssString); // TODO 10毫秒约函数执行时间
  433. setTimeout(() => doElements(cssString, doFunction, document.readyState !== "complete" ? waitMS : waitMS - 10 - settings.getElementTimes, index), settings.getElementTimes);
  434. } else {
  435. console.log("%c未找到 All[" + index + "] " + cssString, settings.fontStyle.error);
  436. }
  437. }
  438.  
  439. function forElement(cssString, doFunction, waitMS = 0, failFunction = null) {
  440. let forElementInterval = setInterval(() => {
  441. if (document.readyState !== "complete" || waitMS > 0) {
  442. let Element = document.querySelector(cssString);
  443. if (Element && Element.nodeType === 1) {
  444. doFunction(Element, forElementInterval);
  445. console.log("%cforElement已为 " + cssString + " 进行了操作", settings.fontStyle.ok);
  446. }
  447. if (document.readyState === "complete") {
  448. waitMS = waitMS - 10 - settings.getElementTimes;
  449. }
  450. } else {
  451. if (failFunction) {
  452. failFunction();
  453. }
  454. console.log("已清除 forElement Interval计时器")
  455. clearInterval(forElementInterval);
  456. }
  457. }, settings.getElementTimes);
  458. }
  459.  
  460. function removeElements(ElementsStrings) {
  461. console.log("正在检测并移除 " + ElementsStrings);
  462. let removeElementsInterval = setInterval(() => {
  463. if (ElementsStrings.length > 0) {
  464. for (let i in ElementsStrings) {
  465. try {
  466. let Elements = eval(ElementsStrings[i]);
  467. if (Elements && Elements.nodeType === 1) {
  468. console.log("%cremoveElemets 执行了移除 " + ElementsStrings[i], settings.fontStyle.ok);
  469. Elements.parentNode.removeChild(Elements);
  470. ElementsStrings.splice(i, 1);
  471. } else if (Elements[0] && Elements[0].nodeType === 1) {
  472. console.log("%cremoveElemets 执行了移除 " + ElementsStrings[i], settings.fontStyle.ok);
  473. for (let Element of Elements) {
  474. Element.parentNode.removeChild(Element);
  475. }
  476. ElementsStrings.splice(i, 1);
  477. }
  478. } catch (e) {
  479. // 排除 null值未找到方法 错误
  480. }
  481. }
  482. } else {
  483. clearInterval(removeElementsInterval);
  484. console.log("Elements 移除完毕");
  485. }
  486. }, 200);
  487. onFirstLoad(() => {
  488. console.log("%cremoveElemets 移除失败 " + ElementsStrings, settings.fontStyle.error);
  489. clearInterval(removeElementsInterval);
  490. });
  491. }
  492.  
  493. if (window === top) {
  494. // 自定义remove方法,暂时用不着了,新方案代替了
  495. // Array.prototype.remove = value => {
  496. // for (let i = 0; i < this.length; i++) {
  497. // if (this[i] === value) {
  498. // this.splice(i, 1);
  499. // return i;
  500. // }
  501. // }
  502. // return -1;
  503. // }
  504. top.addEventListener("message", event => {
  505. if (event.source !== window) {
  506. try {
  507. let sql = key.DECRYPT(event.data, settings.k1, settings.k2).split("\x00");
  508. if (sql[0] === "宝塔镇河妖") {
  509. if (sql[1] === "函数") {
  510. console.log("top执行了函数: " + sql[2]);
  511. eval(sql[2]);
  512. } else if (sql[1] === "请求") {
  513. if (sql[2] === "用户数据库") {
  514. event.source.postMessage(key.ENCRYPT("天王盖地虎\x00给予\x00用户数据库\x00" + JSON.stringify(settings.parseDB), settings.k1, settings.k2), "*");
  515. }
  516. } else if (sql[1] === "给予") {
  517. if (sql[2] === "0") {
  518. if (settings.address !== null) {
  519. settings.address = sql[3];
  520. }
  521. console.log("%c" + settings.address, settings.fontStyle.warn);
  522. } else if (sql[2] === "-1") {
  523. if (settings.address === sql[3]) {
  524. showTip("解析失败,正在更换解析源");
  525. settings.randomSeleceParse();
  526. }
  527. }
  528. } else if (sql[1] === "按下Enter获取焦点") {
  529. onkeydown = e => {
  530. if (e.key === 'Enter') {
  531. event.source.focus();
  532. }
  533. }
  534. }
  535. }
  536. } catch (e) {
  537. console.log("%c" + e, settings.fontStyle.error);
  538. }
  539. }
  540. });
  541.  
  542. if (!detectMobile()) {
  543. if (location.host.indexOf("v.qq.com") !== -1) {
  544. readyPlayerBox("已进入腾讯视频", ["#mask_layer", ".mod_vip_popup", "#mask_layer"], [settings.NoAD解析["OK解析"], settings.NoAD解析["TV解析"], settings.NoAD解析["天翼解析"], settings.NoAD解析["全民解析"]], "div#mod_player", null);
  545. } else if (location.host.indexOf("iqiyi.com") !== -1) {
  546. readyPlayerBox("已进入爱奇艺", ["#playerPopup", "div[class^=qy-header-login-pop]"], [settings.NoAD解析["OK解析"]], "iqpdiv.iqp-player[data-player-hook$=er]", null);
  547. } else if (location.host.indexOf("youku.com") !== -1) {
  548. readyPlayerBox("已进入优酷视频", ["#iframaWrapper"], [], "div#player", null);
  549. } else if (location.host.indexOf("bilibili.com") !== -1) {
  550. doElements("div[role=tooltip]:not([class*=popover-])", loginTip => displayNone(["#" + loginTip[6].id]), 1000, 6);
  551. doElement("svg[aria-hidden=true]", () => readyPlayerBox("已进入哔哩哔哩", null, [settings.NoAD解析["夜幕解析"], settings.NoAD解析["天翼解析"]], "div.bpx-player-video-area,div.mask-container", null)); // TODO || document.getElementById("bilibiliPlayer") || document.getElementById("live-player-ctnr")
  552. } else if (location.host.indexOf("miguvideo.com") !== -1) {
  553. readyPlayerBox("已进入咪咕视频", null, [], "section#mod-player", null);
  554. } else if (location.host.indexOf("le.com") !== -1) {
  555. readyPlayerBox("已进入乐视TV", null, [settings.NoAD解析["云解析"]], "#le_playbox", null);
  556. } else if (location.host.match(/(tv|film).sohu.com/)) {
  557. readyPlayerBox("已进入搜狐视频", null, [settings.NoAD解析["夜幕解析"]], "#player,#sohuplayer,.player-view", null);
  558. } else if (location.host.indexOf("mgtv.com") !== -1) {
  559. readyPlayerBox("已进入芒果TV", null, [settings.NoAD解析["爱解析"], settings.NoAD解析["OK解析"], settings.NoAD解析["全民解析"], settings.NoAD解析["云解析"], settings.NoAD解析["虾米解析"], settings.NoAD解析["夜幕解析"]], "#mgtv-player-wrap", null);
  560. } else if (location.host.indexOf("ixigua.com") !== -1) {
  561. readyPlayerBox("已进入西瓜视频", null, [settings.NoAD解析["夜幕解析"]], "div.teleplayPage__playerSection", null);
  562. } else if (location.host.indexOf("pptv.com") !== -1) {
  563. readyPlayerBox("已进入PPTV", null, [settings.NoAD解析["OK解析"]], "div.w-video", null);
  564. } else if (location.host.indexOf("vip.1905.com") !== -1) {
  565. readyPlayerBox("已进入1905电影网", null, [settings.NoAD解析["云解析"]], "div#playBox", null);
  566. } else if (location.host.indexOf("www.wasu.cn") !== -1) {
  567. readyPlayerBox("已进入华数TV", null, [settings.NoAD解析["OK解析"]], "div#pcplayer", null);
  568. }
  569. } else {
  570. if (location.host.indexOf("v.qq.com") !== -1) {
  571. readyPlayerBox("已进入腾讯视频", [".mod_vip_popup", "[class^=app_],[class^=app-],[class*=_app_],[class*=-app-],[class$=_app],[class$=-app]", "div[dt-eid=open_app_bottom]", "div.video_function.video_function_new", "a[open-app]", "section.mod_source", "section.mod_box.mod_sideslip_h.mod_multi_figures_h,section.mod_sideslip_privileges,section.mod_game_rec"], [settings.NoAD解析["OK解析"]], "div.mod_play:not([style*='display: none;']) section.mod_player", null, href => {
  572. let location = hrefToLocation(href);
  573. href = searchToJSON(location.search);
  574. if (href) {
  575. if (href["cid"]) {
  576. if (href["id"]) {
  577. return location.protocol + '//v.qq.com/detail/' + href["cid"][0] + '/' + href["cid"] + '.html';
  578. } else if (href["vid"]) {
  579. return location.protocol + '//v.qq.com/x/cover/' + href["cid"] + '/' + href["vid"] + '.html';
  580. } else {
  581. return location.protocol + '//v.qq.com/x/cover/' + href["cid"] + '.html';
  582. }
  583. } else if (href["vid"]) {
  584. return location.protocol + '//v.qq.com/x/page/' + href["vid"] + '.html';
  585. } else if (href["lid"]) {
  586. return location.protocol + '//v.qq.com/detail/' + href["lid"][0] + '/' + href["lid"] + '.html';
  587. } else {
  588. return null;
  589. }
  590. } else {
  591. return null;
  592. }
  593. });
  594. } else if (location.host.indexOf("iqiyi.com") !== -1) {
  595. readyPlayerBox("已进入爱奇艺", ["div.m-iqyGuide-layer", "a[down-app-android-url]", "[name=m-extendBar]", "[class*=ChannelHomeBanner]", "section.m-hotWords-bottom"], [settings.NoAD解析["OK解析"]], "section.m-video-player", null);
  596. } else if (location.host.indexOf("youku.com") !== -1) {
  597. readyPlayerBox("已进入优酷视频", ["#iframaWrapper", ".ad-banner-wrapper", ".h5-detail-guide,.h5-detail-vip-guide", ".brief-btm"], [], "#player", null);
  598. } else if (location.host.indexOf("bilibili.com") !== -1) {
  599. readyPlayerBox("已进入哔哩哔哩", ["div.fe-ui-open-app-btn,div.recom-wrapper,open-app-btn", "[class*=openapp]"], [settings.NoAD解析["夜幕解析"], settings.NoAD解析["天翼解析"]], "div#app.main-container div.player-wrapper", null, href => href.replace("m.bilibili.com", "www.bilibili.com"));
  600. } else if (location.host.indexOf("miguvideo.com") !== -1) {
  601. readyPlayerBox("已进入咪咕视频", ["[class^=app_],[class^=app-],[class*=_app_],[class*=-app-],[class$=_app],[class$=-app]", ".openClient", "div.group-item.programgroup .data-rate-01,div.group-item.programgroup .max-rate-01,div.group-item.programgroup .p-common"], [], "section#mod-player", null, href => href.replace("m.miguvideo.com", "www.miguvideo.com").replace("msite", "website"));
  602. } else if (location.host.indexOf("le.com") !== -1) {
  603. (block_show => {
  604. block_show.innerHTML = "div.layout{visibility: visible !important; display:block !important;}div.layout>*:not(style,script,#j-vote,#j-follow){visibility: visible !important; display: block !important;}";
  605. document.head.insertBefore(block_show, document.head.firstChild);
  606. })(document.createElement("style"));
  607. doElement("a.j-close-gdt", jump_over => {
  608. jump_over.click();
  609. return false;
  610. });
  611. readyPlayerBox("已进入乐视TV", ["a.leapp_btn", "div.full_gdt_bits[id^=full][data-url]", "[class*=Daoliu],[class*=daoliu],[class*=game]", "div.m-start", "[class*=icon_user]"], [settings.NoAD解析["云解析"]], "div.column.play", null);
  612. } else if (location.host.indexOf("m.tv.sohu.com") !== -1) {
  613. readyPlayerBox("已进入搜狐视频", ["div[class^=banner]", "div.js-oper-pos", "div[id^=ad],div[id^=ad] *", "[id*=login],[class*=login]", "[class$=-app]", "div.app-vbox.ph-vbox,div.app-vbox.app-guess-vbox", "div.twinfo_iconwrap", "div[class$=banner],div[id$=banner]"], [settings.NoAD解析["夜幕解析"]], "#player,#sohuplayer,.player-view", null, async href => {
  614. return new Promise(resolve => {
  615. xmlHttpRequest({
  616. url: href, success: data => {
  617. let result = data.responseText.match(/var videoData = \{[^\x00]+tvUrl:"(http.+)",[\r\n]/)[1];
  618. resolve(result);
  619. }, error: () => resolve(href)
  620. });
  621. });
  622. });
  623. } else if (location.host.indexOf("mgtv.com") !== -1) {
  624. readyPlayerBox("已进入芒果TV", ["div.adFixedContain,div.ad-banner,div.m-list-graphicxcy.fstp-mark", "div[class^=mg-app],div#comment-id.video-comment div.ft,div.bd.clearfix,div.v-follower-info", "div.ht.mgui-btn.mgui-btn-nowelt", "div.personal", "div[data-v-41c9a64e]"], [settings.NoAD解析["爱解析"], settings.NoAD解析["OK解析"], settings.NoAD解析["全民解析"], settings.NoAD解析["云解析"], settings.NoAD解析["虾米解析"], settings.NoAD解析["夜幕解析"]], "div.video-poster,div.video-area", null);
  625. } else if (location.host.indexOf("ixigua.com") !== -1) {
  626. readyPlayerBox("已进入西瓜视频", ["div.xigua-download", "div.xigua-guide-button", "div.c-long-video-recommend.c-long-video-recommend-unfold"], [settings.NoAD解析["夜幕解析"]], "div.xigua-detailvideo-video", null);
  627. } else if (location.host.indexOf("pptv.com") !== -1) {
  628. readyPlayerBox("已进入PPTV", ["[data-darkreader-inline-bgimage][data-darkreader-inline-bgcolor]", "div[class^=pp-m-diversion]", "section#ppmob-detail-picswiper", "section.layout.layout_ads", "div.foot_app", "div[modulename=导流位]", "a[class*=user]", "div.mod_video_info div.video_func"], [settings.NoAD解析["OK解析"]], "section.pp-details-video", null, href => href.replace("m.pptv.com", "v.pptv.com"));
  629. } else if (location.host.indexOf("vip.1905.com") !== -1) {
  630. (movie_info => {
  631. movie_info.innerHTML = "section#movie_info{padding-top: 20px !important;}";
  632. document.head.appendChild(movie_info);
  633. })(document.createElement("style"));
  634. readyPlayerBox("已进入1905电影网", ["a.new_downLoad[target=_blank]", "iframe[srcdoc^='<img src=']", "section.movieList_new.club_new", ".wakeAppBtn", "[class*=login]", "section.openMembershipBtn", ".ad", ".open-app,.openApp,ul.iconList li:not(.introduceWrap),div#zhichiBtnBox", "section#hot_movie,section#exclusive_movie,section#hot_telve"], [settings.NoAD解析["云解析"]], "div.area.areaShow.clearfix_smile", null);
  635. } else if (location.host.indexOf("www.wasu.cn") !== -1) {
  636. readyPlayerBox("已进入华数TV", ["div.ws_poster", "div.appdown,div.player_menu_con", "div#play_and_info_fix_adv"], [settings.NoAD解析["OK解析"]], "div#player,div#pop", null);
  637. }
  638. }
  639.  
  640. function readyPlayerBox(Tip, displayNones, srcs, cssString, doFunction, doHref = null) {
  641. if (Tip) {
  642. console.log("%c" + Tip, settings.fontStyle.maxTip);
  643. }
  644. onLocationChange(() => location.reload()); // TODO 如果网页rul变了就刷新页面
  645.  
  646. if (displayNones) {
  647. displayNone(displayNones);
  648. }
  649. doElement(cssString, async playerBox => {
  650. setInterval(() => {
  651. for (let link of document.querySelectorAll("a")) {
  652. link.onclick = () => {
  653. if (link.host === location.host) {
  654. location.href = link.href;
  655. }
  656. }
  657. }
  658. }, 1500);
  659.  
  660. let iframe = document.createElement("iframe");
  661. iframe.allowFullscreen = true;
  662. iframe.frameBorder = "0"; // HTML5已弃用此属性,并使用style.border代替
  663. iframe.width = "100%";
  664. iframe.height = "100%";
  665. iframe.style = "background-color: #000 !important; border: 0 !important; display: block !important; visibility: visible !important; opacity: 1 !important;" + " min-width: 100% !important; width: 100% !important; max-width: 100% !important; min-height: 100% !important; height: 100% !important; max-height: 100% !important;" + " position: absolute !important; left: 0px !important; top: 0px !important; z-index: 2147483647 !important; overflow: hidden;";
  666.  
  667. let iframeStartTime, tested = false, others = Object.values(settings.NoAD解析).filter(value => {
  668. // 求出 srcs 在 NoAD解析 中的补集
  669. return srcs.indexOf(value) === -1;
  670. });
  671. settings.randomSeleceParse = async () => {
  672. // arguments 代表输入的所有参数,看不懂可以百度搜索 “js 参数 arguments”
  673. // return arguments ? arguments[Math.floor(Math.random() * arguments.length)] : null;
  674. if (srcs.length > 0) {
  675. let random = Math.floor(Math.random() * srcs.length);
  676. src = srcs[random];
  677. srcs.splice(random, 1);
  678. } else {
  679. if (tested) {
  680. showTip("该视频可能无法解析\n请尝试使用z1解析\n如有疑问请反馈");
  681. return false;
  682. } else {
  683. showTip("解析失败,正在尝试其他解析源");
  684. srcs = others;
  685. others = null;
  686. tested = true;
  687. let random = Math.floor(Math.random() * srcs.length);
  688. src = srcs[random];
  689. srcs.splice(random, 1);
  690. }
  691. }
  692. if (typeof doHref === "function") {
  693. let href = await doHref(location.href);
  694. iframe.src = src ? src + (href ? href : location.href) : "";
  695. } else {
  696. iframe.src = src ? src + location.href : "";
  697. }
  698. iframeStartTime = new Date().getTime();
  699. return true;
  700. }
  701. let src = null;
  702. await settings.randomSeleceParse();
  703. playerBox.style.zIndex = "1";
  704. iframe.onload = () => {
  705. // 判断iframe加载完成的时间
  706. if (new Date().getTime() - iframeStartTime < 500) {
  707. // 如果加载时间小于半秒,并且检测网页加载出错,说明网页有问题。
  708. xmlHttpRequest({
  709. url: iframe.src,
  710. error: () => {
  711. showTip("该解析已失效,已切换推荐解析源");
  712. settings.randomSeleceParse();
  713. }
  714. })
  715. }
  716. }
  717. playerBox.appendChild(iframe);
  718. console.log(iframe);
  719. console.log("%cplayerBox已建立解析连接", settings.fontStyle.maxTip);
  720.  
  721. let DIY_iframe;
  722. settings.DIY_iframeFunction = () => {
  723. if (settings.parseDB.DIY解析栏) {
  724. if (!DIY_iframe || DIY_iframe.constructor.name !== "HTMLDivElement") {
  725. // 自定义解析地址
  726. DIY_iframe = document.createElement("div");
  727. DIY_iframe.style = "display: flex; background-color: #0000; font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; font-size: 15px;" + " position: fixed; height: 30px; width: 86%; transform: translateX(-50%); left: 50%; max-width: 600px; border-radius: 15px; box-shadow: 0 0 6px 2px #444; bottom: 5px;";
  728. DIY_iframe.innerHTML = "<select style='border: 0; background-color: #ddd; text-align: center; min-width: 80px; width: 80px; height: 100%; border-bottom-left-radius: 15px; border-top-left-radius: 15px;'></select>" + "<input type='text' style='border: 0; background-color: #eee; padding-left: 10px; flex-grow: 1; width: 123px; height: 100%;' placeholder='(当前网址请留空)'>" + "<button style='background-color: #4af; border-color: #4af; text-align: center; color: #fff; min-width: 54px; width: 54px; height: 100%; border-bottom-right-radius: 15px; border-top-right-radius: 15px;'>解析</button>";
  729. let DIY_iframe_text = DIY_iframe.querySelector("input[type=text]");
  730.  
  731. async function DIY_iframe_src() {
  732. let newiframe = document.querySelector("iframe[id*=player]");
  733. if (newiframe) {
  734. iframe = newiframe;
  735. }
  736. if (typeof doHref === "function") {
  737. let href = await doHref(DIY_iframe_text.value ? DIY_iframe_text.value : location.href);
  738. iframe.src = DIY_iframe_select.options[DIY_iframe_select.selectedIndex].value + (href ? href : (DIY_iframe_text.value ? DIY_iframe_text.value : location.href))
  739. } else {
  740. iframe.src = DIY_iframe_select.options[DIY_iframe_select.selectedIndex].value + (DIY_iframe_text.value ? DIY_iframe_text.value : location.href);
  741. }
  742. iframeStartTime = new Date().getTime();
  743. }
  744.  
  745. let DIY_iframe_select = DIY_iframe.querySelector("select");
  746. for (let name in settings.NoAD解析) {
  747. DIY_iframe_select.innerHTML += "<option value='" + settings.NoAD解析[name] + "' style='text-align: center'>" + name + "</option>";
  748. }
  749. for (let name in settings.AD解析) {
  750. DIY_iframe_select.innerHTML += "<option value='" + settings.AD解析[name] + "' style='text-align: center; color: #fa0; '>⚠" + name + "</option>";
  751. }
  752. DIY_iframe.querySelector("option[value='" + src + "']").selected = true;
  753. settings.randomSeleceParse = async () => {
  754. // arguments 代表输入的所有参数,看不懂可以百度搜索 “js 参数 arguments”
  755. // return arguments ? arguments[Math.floor(Math.random() * arguments.length)] : null;
  756. if (srcs.length > 0) {
  757. let random = Math.floor(Math.random() * srcs.length);
  758. src = srcs[random];
  759. srcs.splice(random, 1);
  760. DIY_iframe.querySelector("option[value='" + src + "']").selected = true;
  761. } else {
  762. if (tested) {
  763. showTip("该视频可能无法解析\n请尝试使用z1解析\n如有疑问请反馈");
  764. return false;
  765. } else {
  766. showTip("解析失败,正在尝试其他解析源");
  767. srcs = others;
  768. others = null;
  769. tested = true;
  770. let random = Math.floor(Math.random() * srcs.length);
  771. src = srcs[random];
  772. srcs.splice(random, 1);
  773. }
  774. }
  775. settings.address = {"0": 0, "-1": 1};
  776. if (typeof doHref === "function") {
  777. let href = await doHref(location.href);
  778. iframe.src = src ? src + (href ? href : location.href) : "";
  779. } else {
  780. iframe.src = src ? src + location.href : "";
  781. }
  782. iframeStartTime = new Date().getTime();
  783. return true;
  784. }
  785. DIY_iframe.querySelector("button").onclick = () => DIY_iframe_src();
  786. DIY_iframe_text.onkeydown = DIY_iframe_select.onkeydown = event => {
  787. if (event.key === "Enter") {
  788. DIY_iframe_src();
  789. }
  790. }
  791. doElement("toolsbar", toolsBar => {
  792. toolsBar.appendChild(DIY_iframe);
  793. });
  794. } else if (DIY_iframe.style.visibility === "hidden") {
  795. DIY_iframe.style.display = "flex";
  796. DIY_iframe.style.visibility = "";
  797. }
  798. } else if (DIY_iframe && DIY_iframe.constructor.name === "HTMLDivElement" && DIY_iframe.style.visibility === "") {
  799. DIY_iframe.style.display = "none";
  800. DIY_iframe.style.visibility = "hidden";
  801. }
  802. }
  803. settings.DIY_iframeFunction();
  804.  
  805. (waiter => {
  806. waiter /= settings.getElementTimes;
  807. let resetPlayerBoxInterval = setInterval(() => {
  808. let newPlayerBox = document.querySelector(cssString);
  809. if (newPlayerBox !== playerBox && newPlayerBox !== null || newPlayerBox !== null && newPlayerBox.querySelector("iframe[src='" + iframe.src + "']") === null) {
  810. console.log("playerBox重新建立连接");
  811. let src = iframe.src;
  812. iframe.src = "";
  813. iframe = iframe.cloneNode(true);
  814. iframe.src = src;
  815. newPlayerBox.style.zIndex = "1";
  816. newPlayerBox.appendChild(iframe);
  817. clearInterval(resetPlayerBoxInterval);
  818. } else if (document.readyState === "complete" && waiter-- <= 0) {
  819. clearInterval(resetPlayerBoxInterval);
  820. }
  821. }, settings.getElementTimes)
  822. })(0);
  823.  
  824. if (doFunction) {
  825. doFunction(playerBox, iframe);
  826. }
  827. setInterval(() => {
  828. for (let video of document.getElementsByTagName("video")) {
  829. if (video.src) {
  830. video.removeAttribute("src");
  831. video.load();
  832. video.muted = true;
  833. }
  834. }
  835. }, settings.getElementTimes);
  836.  
  837. ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange'].forEach((item, index) => {
  838. window.addEventListener(item, () => {
  839. let toolsBar = document.querySelector("toolsbar");
  840. if (document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen) {
  841. toolsBar.style.display = 'none';
  842. } else {
  843. toolsBar.style.display = 'block';
  844. }
  845. }, true);
  846. });
  847. });
  848. }
  849.  
  850. function hrefToLocation(href) {
  851. let location = {href: href}, c = 0, start = 0, search;
  852. for (let i = 0, port; i < href.length; i++) {
  853. if (href[i] === "/") {
  854. if (++c === 1) {
  855. location.protocol = href.substring(start, i);
  856. } else if (c === 3) {
  857. location.host = href.substring(start + 1, i);
  858. if (port) {
  859. location.port = href.substring(port + 1, i);
  860. } else {
  861. location.hostname = location.host;
  862. location.port = "";
  863. }
  864. }
  865. if (c <= 3) {
  866. start = i;
  867. }
  868. } else if (href[i] === ":" && c === 2) {
  869. location.hostname = href.substring(start + 1, i);
  870. port = i;
  871. } else if (href[i] === "?" && !search) {
  872. location.pathname = href.substring(start, i);
  873. search = i;
  874. } else if (href[i] === "#" && !location.hash) {
  875. location.hash = href.substr(i);
  876. if (location.pathname === undefined) {
  877. location.pathname = href.substring(c, i);
  878. } else if (search) {
  879. location.search = href.substring(search, i);
  880. }
  881. break;
  882. }
  883. }
  884. if (location.pathname === undefined) {
  885. location.pathname = c === 3 ? href.substr(start) : "";
  886. location.search = location.hash = "";
  887. }
  888. if (location.search === undefined) {
  889. if (search) {
  890. location.search = href.substr(search);
  891. } else {
  892. location.search = "";
  893. }
  894. }
  895. if (location.hash === undefined) {
  896. location.hash = "";
  897. }
  898. return location;
  899. }
  900. } else {
  901. async function setParseBox() {
  902. // 移除广告模块
  903. removeElements(['document.getElementById("ADplayer")', 'document.getElementById("ADtip")']);
  904. // 设置解析播放器
  905. setParseVideo();
  906. // 等待数据得到响应,移除弹幕模块
  907. await settings.parseDB;
  908. if (!settings.parseDB.弹幕开关) {
  909. console.log("正在移除弹幕功能");
  910. removeElements(['document.querySelector("div[class$=player-video-wrap]").getElementsByTagName("div")', 'document.querySelector("div[class$=playr-danmu]")', 'document.querySelector("div[class$=player-danmaku]")', 'document.querySelector("div[class*=player-comment-box]")', 'document.querySelector("div[class*=player-controller-mask]")', 'document.querySelector("[class*=player-list-icon]")', 'document.querySelector("div[class$=player-menu]")']);
  911. }
  912. }
  913.  
  914. function setParseVideo() {
  915. console.log(location.href + " 正在查找video 准备移除poster")
  916. forElement("video", (video, thisInterval) => {
  917. if (video.src) {
  918. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00函数\x00settings.address = null", settings.k1, settings.k2), "*");
  919. if (!detectMobile()) {
  920. let fullscreen_btn = document.querySelector("[class*=fullscreen],[class$=player-full] button[class$=full-icon]");
  921. if (fullscreen_btn && fullscreen_btn.nodeType === 1) {
  922. // 阻止事件冒泡
  923. fullscreen_btn.parentNode.parentNode.onkeyup = event => event.stopPropagation();
  924. }
  925. video.onkeyup = event => event.stopPropagation();
  926. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00按下Enter获取焦点", settings.k1, settings.k2), "*")
  927. onkeyup = video.onkeyup = event => {
  928. if (event.key === "Enter") {
  929. if (video.paused) {
  930. video.play();
  931. }
  932. if (fullscreen_btn && fullscreen_btn.nodeType === 1) {
  933. fullscreen_btn.click();
  934. return false;
  935. } else if (video.webkitDisplayingFullscreen) {
  936. if (video.webkitExitFullScreen) {
  937. video.webkitExitFullScreen();
  938. } else if (video.webkitExitFullscreen) {
  939. video.webkitExitFullscreen();
  940. }
  941. } else {
  942. if (video.webkitEnterFullScreen) {
  943. video.webkitEnterFullScreen();
  944. } else if (video.webkitEnterFullscreen) {
  945. video.webkitEnterFullscreen();
  946. }
  947. }
  948. }
  949. }
  950. focus();
  951. showTip("按下Enter回车键,进入全屏 并 自动播放");
  952. video.addEventListener("pause", () => {
  953. if ((video.currentTime - video.duration) > -5) {
  954. console.log("视频播放结束了");
  955. if (fullscreen_btn && fullscreen_btn.nodeType === 1 && ((video.clientWidth || video.scrollWidth) === screen.width) || ((video.clientHeight || video.scrollHeight) === screen.height)) {
  956. fullscreen_btn.click();
  957. return false;
  958. } else if (video.webkitExitFullScreen) {
  959. video.webkitExitFullScreen();
  960. } else if (video.webkitExitFullscreen) {
  961. video.webkitExitFullscreen();
  962. } else {
  963. console.log("不支持退出全屏");
  964. }
  965. }
  966. }, false);
  967. } else {
  968. // showTip("解析成功");
  969. }
  970. clearInterval(thisInterval);
  971. }
  972. }, 3000, function () {
  973. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00给予\x00-1\x00" + location.href, settings.k1, settings.k2), "*");
  974. });
  975. }
  976.  
  977. if (location.host.indexOf("jiexi.t7g.cn") !== -1) {
  978. // 移除爱解析p2p提示
  979. displayNone(["body>div#stats"]);
  980. setParseBox();
  981. } else if (location.host.indexOf("api.okjx.cc:3389") !== -1) {
  982. // 删除OK解析线路选择功能
  983. (style => {
  984. style.innerHTML = ".slide,.panel,.slide *,.panel *{width: 0 !important; max-width: 0 !important; opacity: 0 !important;}";
  985. document.head.appendChild(style);
  986. })(document.createElement("style"));
  987. setParseBox();
  988. } else if (location.host.indexOf("api.jiubojx.com") !== -1) {
  989. displayNone("div.adv_wrap_hh");
  990. setParseBox();
  991. } else if (location.host.indexOf("yemu.xyz") !== -1) {
  992. if (location.pathname.indexOf("jx.php") === -1) {
  993. if (location.host.indexOf("www.yemu.xyz") !== -1) {
  994. // 删除夜幕解析线路选择功能
  995. (style => {
  996. style.innerHTML = ".slide,.panel,.slide *,.panel *{width: 0 !important; max-width: 0 !important; opacity: 0 !important;}";
  997. document.head.appendChild(style);
  998. })(document.createElement("style"));
  999. } else if (location.host.indexOf("jx.yemu.xyz") !== -1) {
  1000. // 移除视频分类提示 及 解析框架处理
  1001. displayNone(["div.advisory"]);
  1002. setParseBox();
  1003. }
  1004. } else {
  1005. // 移除背景图片
  1006. doElement("div[style*='width:100%;height:100%;'][style*='.jpg']", background => {
  1007. background.style = "width:100%;height:100%;position:relative;z-index:2147483647987;";
  1008. }, 5000);
  1009. }
  1010. } else if (location.host.indexOf('www.mtosz.com') !== -1) {
  1011. displayNone([".video-panel-blur-image"]); // 似乎不管用?
  1012. doElement(".video-panel-blur-image", element => {
  1013. element.style = "display: none; height: 0; width: 0;";
  1014. });
  1015. setParseBox();
  1016. } else if (location.host.indexOf('v.superchen.top:3389') !== -1) {
  1017. setParseBox();
  1018. } else if (location.host.indexOf('jx.parwix.com:4433') !== -1) {
  1019. setParseBox();
  1020. } else if (location.pathname) {
  1021. setParseVideo();
  1022. }
  1023. }
  1024.  
  1025.  
  1026. function displayNone(Tags) {
  1027. let style = document.createElement("style");
  1028. style.innerHTML = "\n";
  1029. for (let i = 0; i < Tags.length; i++) {
  1030. style.innerHTML += Tags[i] + "{display: none !important; height: 0 !important; width: 0 !important; visibility: hidden !important; max-height: 0 !important; max-width: 0 !important; opacity: 0 !important;}\n";
  1031. }
  1032. document.head.insertBefore(style, document.head.firstChild);
  1033. }
  1034.  
  1035. function onLocationChange(handler) {
  1036. let url = top.location.pathname;
  1037. let onLocationChangeInterval = setInterval(() => {
  1038. let href = top.location.pathname;
  1039. if (href.indexOf(url) === -1) {
  1040. handler();
  1041. clearInterval(onLocationChangeInterval);
  1042. } else {
  1043. url = href;
  1044. }
  1045. }, settings.getElementTimes);
  1046. }
  1047.  
  1048. function onFirstLoad(doFunction) {
  1049. if (document.readyState === "complete") {
  1050. if (doFunction) {
  1051. doFunction();
  1052. }
  1053. } else {
  1054. setTimeout(() => {
  1055. onFirstLoad(doFunction);
  1056. }, settings.getElementTimes);
  1057. }
  1058. }
  1059.  
  1060. function searchToJSON(search) {
  1061. if (search) {
  1062. return JSON.parse("{\"" + decodeURIComponent(search.substring(1)
  1063. .replace(/"/g, '\\"')
  1064. .replace(/&/g, '","')
  1065. .replace(/=/g, '":"')) + "\"}");
  1066. } else {
  1067. return null;
  1068. }
  1069. }
  1070. }
  1071.  
  1072. function showTip(msg, style = "") {
  1073. // 该函数需要在top内运行,否则可能显示异常
  1074. if (window === top) {
  1075. let tip = document.querySelector(":root>tip");
  1076. if (tip && tip.nodeType === 1) {
  1077. // 防止中途新的showTip事件创建多个tip造成卡顿
  1078. root.removeChild(tip);
  1079. }
  1080. tip = document.createElement("tip");
  1081. // pointer-events: none; 禁用鼠标事件,input标签使用 disabled='disabled' 禁用input标签
  1082. tip.style = style + "pointer-events: none; opacity: 0; background-color: #222a; color: #fff; font-family: 微软雅黑,黑体,Droid Serif,Arial,sans-serif; font-size: 20px; text-align: center; padding: 6px; border-radius: 16px; position: fixed; transform: translate(-50%, -50%); left: 50%; bottom: 15%; z-index: 2147483647;";
  1083. tip.innerHTML = "<style>@keyframes showTip {0%{opacity: 0;} 33.34%{opacity: 1;} 66.67%{opacity: 1;} 100%{opacity: 0;}}</style>\n" + msg;
  1084. let time = msg.replace(/\s/, "").length / 2; // TODO 2个字/秒
  1085. // cubic-bezier(起始点, 起始点偏移量, 结束点偏移量, 结束点),这里的 cubic-bezier函数 表示动画速度的变化规律
  1086. tip.style.animation = "showTip " + (time > 2 ? time : 2) + "s cubic-bezier(0," + ((time - 1) > 0 ? (time - 1) / time : 0) + "," + (1 - ((time - 1) > 0 ? (time - 1) / time : 0)) + ",1) 1 normal";
  1087. root.appendChild(tip);
  1088. setTimeout(() => {
  1089. try {
  1090. root.removeChild(tip);
  1091. } catch (e) {
  1092. // 排除root没有找到tip
  1093. }
  1094. }, time * 1000);
  1095. } else {
  1096. top.postMessage(key.ENCRYPT("宝塔镇河妖\x00函数\x00showTip('" + msg + "')", settings.k1, settings.k2), "*");
  1097. }
  1098. }
  1099.  
  1100. function xmlHttpRequest(settings) {
  1101. let request = new XMLHttpRequest();
  1102. if (settings.success) {
  1103. request.onload = event => {
  1104. // 加载成功
  1105. settings.success(request, event);
  1106. }
  1107. }
  1108. if (settings.error) {
  1109. request.onerror = event => {
  1110. // 加载失败
  1111. settings.error(request, event);
  1112. }
  1113. }
  1114. if (settings.loadend) {
  1115. request.onloadend = event => {
  1116. // 加载结束
  1117. settings.loadend(request, event);
  1118. }
  1119. }
  1120. if (settings.timeout) {
  1121. request.ontimeout = event => {
  1122. // 加载超时
  1123. settings.timeout(request, event);
  1124. }
  1125. }
  1126. request.open(settings.method ? settings.method : "GET", settings.url ? settings.url : location.href, settings.async ? settings.async : true, settings.username ? settings.username : null, settings.password ? settings.password : null);
  1127. if (settings.headers) {
  1128. for (let header in settings.headers) {
  1129. request.setRequestHeader(header, settings[header]);
  1130. }
  1131. }
  1132. if (settings.dataType) {
  1133. request.responseType = settings.dataType;
  1134. }
  1135. if (settings.data) {
  1136. let data = "";
  1137. for (let key in settings.data) {
  1138. data += key + "=" + settings.data[key] + "&";
  1139. }
  1140. data = data.substr(0, data.length - 1);
  1141. request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  1142. request.send(data);
  1143. } else {
  1144. request.send();
  1145. }
  1146. return request;
  1147. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址