Greasy Fork is available in English.
适配手机端与电脑端
当前为
// ==UserScript==
// @name 🌀VIP视频解析——fatcat
// @namespace [fatcat]
// @version 2.0
// @description 适配手机端与电脑端
// @author 暴走的肥猫
// @license MIT, Sign after modification
// @include /^http[^http]*youku\.com\/.+$/
// @include /^http[^http]*iqiyi\.com\/.+$/
// @include /^http[^http]*v\.qq\.com\/.+$/
// @include /^http[^http]*le\.com\/.+$/
// @include /^http[^http]*mgtv\.com\/.+$/
// @include /^http[^http]*tv\.sohu\.com\/.+$/
// @compatible safari
// @compatible chrome
// @compatible edge
// @grant GM_getValue
// @grant GM_setValue
// @grant GM.getValue
// @grant GM.setValue
// @run-at document-idle
// @noframes
// ==/UserScript==
/*jshint esversion: 11 */
(async function () {
const ACCESS_POINT = [
{ "name": "夜幕", "url": "https://www.yemu.xyz/?url=" },
{ "name": "综合", "url": "https://jx.jsonplayer.com/player/?url=" },
{ "name": "CK", "url": "https://www.ckplayer.vip/jiexi/?url=" },
{ "name": "YT", "url": "https://jx.yangtu.top/?url=" },
{ "name": "Player-JY", "url": "https://jx.playerjy.com/?url=" },
{ "name": "yparse", "url": "https://jx.yparse.com/index.php?url=" },
{ "name": "8090", "url": "https://www.8090g.cn/?url=" },
{ "name": "剖元", "url": "https://www.pouyun.com/?url=" },
{ "name": "虾米", "url": "https://jx.xmflv.com/?url=" },
{ "name": "全民", "url": "https://43.240.74.102:4433?url=" },
{ "name": "爱豆", "url": "https://jx.aidouer.net/?url=" },
{ "name": "m1907", "url": "https://im1907.top/?jx=" },
{ "name": "M3U8TV", "url": "https://jx.m3u8.tv/jiexi/?url=" },
{ "name": "冰豆", "url": "https://bd.jx.cn/?url=" },
{ "name": "playm3u8", "url": "https://www.playm3u8.cn/jiexi.php?url=" },
];
async function getUserConfig(key, defaultVal) {
return GM_getValue ? GM_getValue(key, defaultVal) : GM.getValue(key, defaultVal);
}
async function setUserConfig(key, val) {
return GM_setValue ? GM_setValue(key, val) : GM.setValue(key, val);
}
async function pauseAllVideos() {
let i = 0;
let interval = setInterval(function () {
i++;
if (i > 1200) clearInterval(interval);
document.querySelectorAll('video').forEach(video => { video.pause(); video.style.visibility = 'hidden'; });
}, 100);
}
function seekSameSizeParentNode(node) {
let parentSize = node.parentElement.getBoundingClientRect();
let nodeSize = node.getBoundingClientRect();
if (parentSize.width - nodeSize.width < 1 && parentSize.height - nodeSize.height < 1) return seekSameSizeParentNode(node.parentElement);
return node
}
function useInterval(fn, intervalTime, maxTime) {
return new Promise((resolve) => {
let totalTime = 0;
let interval = setInterval(() => {
totalTime += intervalTime;
if (totalTime >= maxTime || fn()) { clearInterval(interval); resolve(); }
}, intervalTime)
})
}
async function findVideoWrapper() {
await useInterval(() => Array.from(document.querySelectorAll('video')).find(videoNode => {
videoNode.style.display = 'revert';
return videoNode.getBoundingClientRect().width > 100 && videoNode.getBoundingClientRect().height > 100
}), 200, Infinity);
let videoNodes = Array.from(document.querySelectorAll('video'));
return videoNodes.map(videoNode => seekSameSizeParentNode(videoNode)).reduce((pre, cur) => {
let preW = pre?.getBoundingClientRect().width || 0;
let curW = cur.getBoundingClientRect().width;
if (curW > preW) return cur;
return pre;
})
}
async function createVideoFrame(videoWrapper, lastAccessPoint) {
videoWrapper.style.overflow = 'hidden';
let iframeWrapper = document.createElement('div');
iframeWrapper.innerHTML = `<iframe src="${lastAccessPoint.url}${window.location.href}" width="100%" height="100%" allowfullscreen id="fatcat_video_vip_iframe" style="border:none;"/>`;
iframeWrapper.style = `position:absolute; inset:0; z-index: 99999999;`
videoWrapper.appendChild(iframeWrapper);
return;
}
async function createMenu(accessPoints, lastAccessPoint) {
if (document.querySelector('#fatcat_video_vip')) return;
let wrapper = document.createElement('div');
wrapper.innerHTML = `
<div id="fatcat_video_vip">
<style>
#fatcat_video_vip {
position: fixed;
bottom: 0;
right: 0;
z-index: 99999998;
font-size: 17px;
}
#fatcat_video_vip_link button{
cursor: pointer;
border-radius: 12px 0 0 0;
padding: 20px;
font-weight: bolder;
background: linear-gradient(to top right, rgba(129, 215, 14, 1) 0%, rgba(46, 159, 248, 1) 100%);
color: white;
}
</style>
<select id="fatcat_video_vip_select">
${accessPoints.map(({ name, url }) => `<option value="${url}" ${name == lastAccessPoint.name ? 'selected' : ''}>${name}</option>`).join()}
</select>
<a href="${lastAccessPoint.url}${window.location.href}" target="_blank" id="fatcat_video_vip_link"><button>外部播放</button></a>
</div>
`;
let selects = wrapper.querySelector('#fatcat_video_vip_select');
let aTag = wrapper.querySelector('#fatcat_video_vip_link');
function updateLink() {
let val = selects.value;
aTag.href = val + window.location.href;
let iframe = document.querySelector('#fatcat_video_vip_iframe');
if (iframe.src != (val + window.location.href)) {
iframe.src = val + window.location.href;
setUserConfig('lastAccessPoint', accessPoints.find(({ url }) => url == val));
return true;
}
}
window.addEventListener('mousedown', (e) => {
if (!(e.target.matches("#fatcat_video_vip *") || e.target.matches("#fatcat_video_vip_iframe"))) {
useInterval(updateLink, 100, 10000);
}
});
selects.onchange = updateLink;
document.body.appendChild(wrapper);
}
async function inject() {
let accessPoints = await getUserConfig('accessPoints');
if (!accessPoints) { setUserConfig('accessPoints', ACCESS_POINT); accessPoints = ACCESS_POINT; }
let lastAccessPoint = await getUserConfig('lastAccessPoint');
if (!lastAccessPoint) { setUserConfig('lastAccessPoint', ACCESS_POINT[0]); lastAccessPoint = ACCESS_POINT[0]; }
let videoWrapper = await findVideoWrapper();
await new Promise(resolve => { document.readyState == 'complete' ? resolve() : window.addEventListener('load', resolve) });
pauseAllVideos();
createVideoFrame(videoWrapper, lastAccessPoint);
createMenu(accessPoints, lastAccessPoint);
}
inject();
})();