💖 VIP视频解析

自用视频解析、多源切换、简洁易用、UI美观(支持"爱优腾芒"等多平台多解析源切换)双击可能更好用哦!

安裝腳本?
作者推薦腳本

您可能也會喜歡 自动跳转所有url链接-外链

安裝腳本
  1. // ==UserScript==
  2. // @name 💖 VIP视频解析
  3. // @namespace https://gf.qytechs.cn/zh-CN/users/1409010-i-breathe
  4. // @version 5.1
  5. // @description 自用视频解析、多源切换、简洁易用、UI美观(支持"爱优腾芒"等多平台多解析源切换)双击可能更好用哦!
  6. // @author I-Breathe
  7. // @include http*://*.iqiyi.*/*
  8. // @include http*://*.qq.*/*
  9. // @include http*://*.youku.*/*
  10. // @include http*://*.bilibili.*/*
  11. // @include http*://*.mgtv.*/*
  12. // @include http*://*.sohu.*/*
  13. // @include http*://*.pptv.*/*
  14. // @include http*://*.le.*/*
  15. // @include http*://*.1905.*/*
  16. // @include http*://*.acfun.*/*
  17. // @grant GM_setValue
  18. // @grant GM_getValue
  19. // @grant GM_deleteValue
  20. // @run-at document-start
  21. // ==/UserScript==
  22.  
  23. (() => {
  24. 'use strict';
  25. const CONFIG = {
  26. buttonSize: 50,
  27. buttonRight: '25px',
  28. buttonBottom: '35px',
  29. imageUrl: GM_getValue('imageUrl', 'https://img13.360buyimg.com/ddimg/jfs/t1/121241/11/19612/181715/5fbac680E636138b5/267dd280e727aff4.jpg'),
  30. opacity: 1,
  31. buttonRadius: '50%',
  32. listBlur: '10px',
  33. listBgColor: 'rgba(20,20,20,0.5)',
  34. listColor: '#00000099',
  35. listFontSize: '14px',
  36. itemHoverBg: 'rgba(255,255,255,0.2)',
  37. selectedColor: '#FFFFFA',
  38. breatheColors: ['#FF00FF95', '#00FAFF95', '#FFFF0095', '#00FFFF95', '#00FF0095'],
  39. breatheDuration: 12,
  40. glowSize: 7,
  41. parseUrl: GM_getValue('selectedParseUrl', 'https://jx.2s0.cn/player/?url='),
  42. parseUrls: GM_getValue('storedParseUrls', [
  43. ["https://bd.jx.cn/?url=", "冰豆弹幕"],
  44. ["https://am1907.top/?jx=", "1907解析"],
  45. ["https://jx.xmflv.cc/?url=", "虾米解析"],
  46. ["https://jx.xymp4.cc/?url=", "咸鱼解析"],
  47. ["https://www.yemu.xyz/?url=", "夜幕解析"],
  48. ["https://jx.77flv.cc/?url=", "77云解析"],
  49. ["https://www.8090g.cn/jiexi/?url=", "8090g"],
  50. ["https://jx.playerjy.com/?url=", "PlayerJy"],
  51. ["https://www.ckplayer.vip/jiexi/?url=", "CkPlay"],
  52. ["https://www.pangujiexi.com/jiexi/?url=", "盘古解析"],
  53. ["https://jx.hls.one/?url=", "hls解析"],
  54. ["https://jx.973973.xyz/?url=", "973播放"],
  55. ["https://jx.nnxv.cn/tv.php?url=", "七哥解析"],
  56. ["https://jx.2s0.cn/player/?url=", "极速高清"],
  57. ["https://rdfplayer.mrgaocloud.com/player/?url=", "红狐解析"],
  58. ["https://jx.m3u8.tv/jiexi/?url=", "M3U8"],
  59. ["https://www.pouyun.com/?url=", "剖云解析"],
  60. ["https://www.playm3u8.cn/jiexi.php?url=", "playm3u8"],
  61. ["https://yparse.ik9.cc/?url=", "ik9云解析"],
  62. ["https://xiaoapi.cn/API/jx_txsp.php?url=", "腾讯API解析"],
  63. ["https://xiaoapi.cn/API/jx_yk.php?url=", "优酷API解析"],
  64. ["https://xiaoapi.cn/API/zs_ewm.php?msg=", "网址生成二维码"],
  65. ["https://bd.jx.cn/?url=", "+"],
  66. ["set", "• • •"]
  67. ])
  68. };
  69.  
  70. let floatingButton, clickTimer, idleTimer;
  71.  
  72. const createStyle = (id, content) => {
  73. const style = document.createElement('style');
  74. if (id) style.id = id;
  75. style.textContent = content;
  76. document.head.appendChild(style);
  77. };
  78.  
  79. createStyle('base-style', `.floating-button{position:fixed;z-index:999999;cursor:pointer;transition:all 0.3s ease;box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[0]}}.source-list{position:fixed;border-radius:16px;border:1px solid rgba(255,255,255,0.1);box-shadow:0 2px 10px rgba(0,0,0,0.2);z-index:999999;padding:1px;min-width:150px;font-family:"Microsoft YaHei",sans-serif}.source-item{padding:4px 20px;border-radius:50px;cursor:pointer;white-space:nowrap;transition:all 0.2s;text-align:center}@keyframes breathe{0%{box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[0]}}25%{box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[1]}}50%{box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[2]}}75%{box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[1]}}100%{box-shadow:0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[0]}}}`);
  80.  
  81. const updateStyles = () => createStyle('dynamic-styles', `.floating-button{border-radius:${GM_getValue('buttonRadius',CONFIG.buttonRadius)}}.source-list{backdrop-filter:blur(${GM_getValue('listBlur',CONFIG.listBlur)});background:${GM_getValue('listBgColor',CONFIG.listBgColor)};color:${GM_getValue('listColor',CONFIG.listColor)};font-size:${GM_getValue('listFontSize',CONFIG.listFontSize)}}.source-item:hover{background:${GM_getValue('itemHoverBg',CONFIG.itemHoverBg)};color:#FFFFFA;font-weight:bold}.selected{color:${GM_getValue('selectedColor',CONFIG.selectedColor)}!important;font-weight:bold}`);
  82. updateStyles();
  83.  
  84. const createElement = (tag, props) => {
  85. const el = document.createElement(tag);
  86. Object.entries(props).forEach(([k, v]) => el[k] = v);
  87. return el;
  88. };
  89.  
  90. const createFloatingButton = () => {
  91. return createElement('img', {
  92. className: 'floating-button',
  93. src: GM_getValue('imageUrl', CONFIG.imageUrl),
  94. style: `right:${GM_getValue('buttonRight',CONFIG.buttonRight)};bottom:${GM_getValue('buttonBottom',CONFIG.buttonBottom)};width:${GM_getValue('buttonSize',CONFIG.buttonSize)}px;height:${GM_getValue('buttonSize',CONFIG.buttonSize)}px;opacity:${GM_getValue('opacity',CONFIG.opacity)};animation:breathe ${GM_getValue('breatheDuration',CONFIG.breatheDuration)}s infinite`
  95. });
  96. };
  97.  
  98. const createListItem = ([url, name], isSetting) => {
  99. const item = createElement('div', {
  100. className: `source-item${url === CONFIG.parseUrl && !isSetting ? ' selected' : ''}`,
  101. textContent: name
  102. });
  103.  
  104. if (url === 'set') {
  105. let clickTimer;
  106. item.addEventListener('click', (e) => {
  107. e.stopPropagation();
  108. clearTimeout(clickTimer);
  109. clickTimer = setTimeout(() => {
  110. const input = prompt('输入格式:名称,URL丨示例:解析1,https://jx.hls.one/?url=');
  111. if (input) {
  112. const [n, u] = input.split(',').map(s => s.trim());
  113. if (n && u) {
  114. CONFIG.parseUrls.splice(-2, 0, [u, n]);
  115. GM_setValue('storedParseUrls', CONFIG.parseUrls);
  116. }
  117. }
  118. }, 200);
  119. });
  120.  
  121. item.addEventListener('dblclick', (e) => {
  122. clearTimeout(clickTimer);
  123. showSettingsPanel();
  124. });
  125. return item;
  126. }
  127.  
  128. if (!isSetting && url !== 'help') {
  129. item.addEventListener('dblclick', (e) => {
  130. e.stopPropagation();
  131. if (confirm(`确认删除 ${name} 解析源?`)) {
  132. CONFIG.parseUrls = CONFIG.parseUrls.filter(v => v[0] !== url);
  133. GM_setValue('storedParseUrls', CONFIG.parseUrls);
  134. item.remove();
  135. }
  136. });
  137. }
  138.  
  139. item.addEventListener('click', (e) => {
  140. if (item.dataset.func) return;
  141. e.stopPropagation();
  142. if (!isSetting) {
  143. document.querySelectorAll('.source-item').forEach(i => i.classList.remove('selected'));
  144. item.classList.add('selected');
  145. GM_setValue('selectedParseUrl', CONFIG.parseUrl = url);
  146. }
  147. document.getElementById('parse-source-list')?.remove();
  148. });
  149.  
  150. return item;
  151. };
  152.  
  153. const showSettingsPanel = () => {
  154. document.querySelectorAll('#parse-source-list').forEach(p => p.remove());
  155. const panel = createElement('div', {
  156. id: 'parse-source-list',
  157. className: 'source-list',
  158. style: `right:${CONFIG.buttonRight};bottom:calc(${CONFIG.buttonBottom} + ${CONFIG.buttonSize + 10}px)`
  159. });
  160.  
  161. const settings = [
  162. ['parseList', '解析列表'],
  163. ['listBgColor', '背景颜色'],
  164. ['listBlur', '模糊强度'],
  165. ['listFontSize', '字体大小'],
  166. ['listColor', '字体颜色'],
  167. ['selectedColor', '选中颜色'],
  168. ['itemHoverBg', '悬停背景'],
  169. ['imageUrl', '更换图标'],
  170. ['buttonRadius', '图标圆角'],
  171. ['reset', '恢复默认']
  172. ];
  173.  
  174. settings.forEach(([key, label]) => {
  175. const item = createListItem([key, label], true);
  176. item.addEventListener('click', () => {
  177. if (key === 'reset') {
  178. if (confirm('即将清除所有配置!确认重置吗?')) {
  179. GM_deleteValue('storedParseUrls');
  180. GM_deleteValue('selectedParseUrl');
  181. Object.keys(CONFIG).forEach(k => GM_deleteValue(k));
  182. location.reload(true);
  183. }
  184. return;
  185. }
  186.  
  187. if (key === 'parseList') {
  188. showParseListPanel();
  189. return;
  190. }
  191.  
  192. const val = prompt(`设置${key} (当前:${GM_getValue(key, CONFIG[key])})`, GM_getValue(key, CONFIG[key]));
  193. if (val !== null) {
  194. GM_setValue(key, val);
  195. updateStyles();
  196. if (key === 'imageUrl') floatingButton.src = val;
  197. }
  198. panel.remove();
  199. });
  200. panel.appendChild(item);
  201. });
  202.  
  203. const closeHandler = (e) => {
  204. if (!panel.contains(e.target) && e.target !== floatingButton) {
  205. panel.remove();
  206. document.removeEventListener('click', closeHandler);
  207. }
  208. };
  209. document.addEventListener('click', closeHandler);
  210. document.body.appendChild(panel);
  211. };
  212.  
  213. const showParseListPanel = () => {
  214. document.querySelectorAll('#parse-source-list').forEach(p => p.remove());
  215.  
  216. const panel = createElement('div', {
  217. id: 'parse-source-list',
  218. className: 'source-list',
  219. style: `
  220. right: ${CONFIG.buttonRight};
  221. bottom: calc(${CONFIG.buttonBottom} + ${CONFIG.buttonSize + 10}px);
  222. max-width: 366px;
  223. max-height: 60vh;
  224. overflow-y: auto;
  225. `
  226. });
  227.  
  228. const title = createElement('div', {
  229. className: 'source-item',
  230. textContent: '当前解析源(双击删除)',
  231. style: 'font-weight:bold;color: #000;'
  232. });
  233. panel.appendChild(title);
  234.  
  235. CONFIG.parseUrls
  236. .filter(([url]) => url !== 'set')
  237. .forEach(([url, name]) => {
  238. const item = createElement('div', {
  239. className: 'source-item',
  240. textContent: `${name} : ${url}`,
  241. title: '双击删除此解析源'
  242. });
  243.  
  244. item.addEventListener('dblclick', () => {
  245. CONFIG.parseUrls = CONFIG.parseUrls.filter(([u]) => u !== url);
  246. GM_setValue('storedParseUrls', CONFIG.parseUrls);
  247. item.remove();
  248. showParseListPanel();
  249. });
  250.  
  251. panel.appendChild(item);
  252. });
  253.  
  254. const addForm = createElement('div', {
  255. className: 'source-item',
  256. style: 'display:flex;gap:5px;padding:1px 8px;'
  257. });
  258.  
  259. const input = createElement('input', {
  260. type: 'text',
  261. placeholder: '格式:名称,URL',
  262. style: 'flex:1;text-align:center;border-radius:18px;border:none;'
  263. });
  264.  
  265. const addBtn = createElement('button', {
  266. textContent: '+ 添加',
  267. style: 'text-align:center;padding:3px 8px;border-radius:12px;background:#2196F3;color:white;border:none;',
  268. onclick: () => {
  269. const [name, url] = input.value.split(',').map(s => s.trim());
  270. if (name && url) {
  271. CONFIG.parseUrls.unshift([url, name]);
  272. GM_setValue('storedParseUrls', CONFIG.parseUrls);
  273. input.value = '';
  274. showParseListPanel();
  275. }
  276. }
  277. });
  278.  
  279. addForm.appendChild(input);
  280. addForm.appendChild(addBtn);
  281. panel.appendChild(addForm);
  282.  
  283. const closeHandler = (e) => {
  284. if (!panel.contains(e.target) && e.target !== floatingButton) {
  285. panel.remove();
  286. document.removeEventListener('click', closeHandler);
  287. }
  288. };
  289.  
  290. document.addEventListener('click', closeHandler);
  291. document.body.appendChild(panel);
  292. };
  293.  
  294. const initButtonEvents = () => {
  295. floatingButton.addEventListener('mouseenter', () => {
  296. floatingButton.style.opacity = '1';
  297. floatingButton.style.transform = 'scale(1.1)';
  298. });
  299.  
  300. floatingButton.addEventListener('mouseleave', () => {
  301. floatingButton.style.opacity = GM_getValue('opacity', CONFIG.opacity);
  302. floatingButton.style.transform = 'none';
  303. });
  304.  
  305. floatingButton.addEventListener('click', () => {
  306. clearTimeout(clickTimer);
  307. clickTimer = setTimeout(() => window.open(GM_getValue('parseUrl', CONFIG.parseUrl) + location.href), 250);
  308. });
  309.  
  310. floatingButton.addEventListener('dblclick', () => {
  311. clearTimeout(clickTimer);
  312. document.querySelectorAll('#parse-source-list').forEach(p => p.remove());
  313.  
  314. const list = createElement('div', {
  315. id: 'parse-source-list',
  316. className: 'source-list',
  317. style: `
  318. right: ${CONFIG.buttonRight};
  319. bottom: calc(${CONFIG.buttonBottom} + ${CONFIG.buttonSize + 10}px);
  320. `
  321. });
  322.  
  323. CONFIG.parseUrls.forEach(item => list.appendChild(createListItem(item)));
  324.  
  325. const closeHandler = (e) => {
  326. if (!list.contains(e.target) && e.target !== floatingButton) {
  327. list.remove();
  328. document.removeEventListener('click', closeHandler);
  329. }
  330. };
  331.  
  332. document.addEventListener('click', closeHandler);
  333. document.body.appendChild(list);
  334. });
  335.  
  336. const initIdleMode = () => {
  337. const enterIdle = () => {
  338. floatingButton.style.opacity = '0.8';
  339. floatingButton.style.animationPlayState = 'paused';
  340. };
  341.  
  342. const exitIdle = () => {
  343. floatingButton.style.opacity = GM_getValue('opacity', CONFIG.opacity);
  344. floatingButton.style.animationPlayState = 'running';
  345. };
  346.  
  347. const resetTimer = () => {
  348. clearTimeout(idleTimer);
  349. exitIdle();
  350. idleTimer = setTimeout(enterIdle, 10000);
  351. };
  352.  
  353. ['mouseenter', 'click', 'dblclick'].forEach(evt =>
  354. floatingButton.addEventListener(evt, resetTimer)
  355. );
  356.  
  357. resetTimer();
  358. };
  359.  
  360. initIdleMode();
  361. };
  362.  
  363. const init = () => {
  364. floatingButton = createFloatingButton();
  365. document.body.appendChild(floatingButton);
  366. initButtonEvents();
  367. };
  368.  
  369. document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', init) : init();
  370. })();

QingJ © 2025

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