// ==UserScript==
// @name 💖 VIP视频解析
// @namespace https://viayoo.com/
// @version 1.2
// @description 视频解析脚本(支持多解析源切换)
// @author I-Brathe
// @run-at document-start
// @match http*://*.iqiyi.*/*
// @match http*://*.qq.*/*
// @match http*://*.youku.*/*
// @match http*://*.bilibili.*/*
// @match http*://*.mgtv.*/*
// @match http*://*.sohu.*/*
// @match http*://*.pptv.*/*
// @match http*://*.le.*/*
// @match http*://*.1905.*/*
// @match http*://*.acfun.*/*
// @grant none
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
// ====== 配置区 ======
const CONFIG = {
// 按钮参数
buttonSize: 50, // 按钮尺寸(px)
buttonRight: '25px', // 距右侧距离
buttonBottom: '30px', // 距底部距离
imageUrl: 'https://img13.360buyimg.com/ddimg/jfs/t1/121241/11/19612/181715/5fbac680E636138b5/267dd280e727aff4.jpg', // 按钮图片
opacity: 0.99, // 默认透明度
// 呼吸灯效果参数
breatheColors: ['#FF00FF95','#00FAFF95','#FFFF0095','#00FFFF95','#00FF0095'], // 颜色渐变序列
breatheDuration: 25, // 呼吸周期(秒)
glowSize: 7, // 光晕尺寸(px)
// 解析接口配置
parseUrl: GM_getValue('selectedParseUrl', 'https://www.yemu.xyz/?url='), // 当前使用的解析接口
// 解析源列表 [接口地址, 显示名称]
parseUrls: [
["https://www.yemu.xyz/?url=", "夜幕解析"],
["https://jx.xmflv.cc/?url=", "虾米解析"],
["https://jx.xymp4.cc/?url=", "咸鱼解析"],
["https://www.8090g.cn/jiexi/?url=", "8090"],
["http://jx.66666zy.top/?url=", "蓝枫蓝光"],
["https://vip.bljiex.com/?v=", "BL解析"],
["https://jx.i2g.cn/?url=", "爱狗解析"],
["https://am1907.top/?jx=", "1907解析"],
["https://bd.jx.cn/?url=", "冰豆弹幕"],
[" ", "• • •"]
]
};
// ====== 全局变量 ======
let floatingButton; // 浮动按钮引用
let clickTimer; // 单击事件计时器
// ====== 样式定义 ======
const styleSheet = document.createElement('style');
styleSheet.textContent = `
/* 浮动按钮基础样式 */
.floating-button {
position: fixed; /* 固定定位 */
z-index: 999999; /* 确保在最顶层 */
cursor: pointer; /* 鼠标手势 */
border-radius: 50%; /* 圆形按钮 */
transition: all 0.3s ease; /* 平滑过渡效果 */
}
/* 弹出列表容器样式 */
.source-list {
position: fixed; /* 固定定位 */
background: #fff; /* 默认背景色 (可修改) */
border-radius: 8px; /* 圆角大小 */
box-shadow: 0 2px 10px rgba(0,0,0,0.2); /* 投影效果 */
z-index: 999999; /* 层级设置 */
padding: 10px 0; /* 内边距 */
min-width: 150px; /* 最小宽度 */
/* 毛玻璃特效样式 (已启用) */
background: rgba(0,0,0,0.5); /* 背景透明度 (0-1) */
backdrop-filter: blur(10px); /* 模糊强度 */
border: 1px solid rgba(255,255,255,0.1); /* 边框效果 */
/* 字体相关设置 */
color: #fff; /* 列表全局字体颜色 (推荐亮色) */
font-family: "Microsoft YaHei", sans-serif; /* 字体设置 */
}
/* 单个列表项样式 */
.source-item {
padding: 8px 20px; /* 项内边距 */
cursor: pointer; /* 鼠标手势 */
font-size: 15px; /* 字体大小 */
white-space: nowrap; /* 禁止换行 */
transition: all 0.2s; /* 过渡动画 */
text-align: center; /* 文字居中 */
/* 颜色自定义区 */
color: inherit; /* 继承列表字体颜色 */
/* color: #333; */ /* 独立项字体颜色 (取消注释使用) */
/* 悬停效果 */
&:hover {
background: rgba(255,255,255,0.1); /* 悬停背景色 */
/* color: #FF4081; */ /* 悬停字体颜色 (示例) */
}
/* 当前选中项样式 */
&[data-selected="true"] {
color: #FF4081; /* 选中项颜色 */
font-weight: bold; /* 加粗显示 */
}
}
/* 呼吸灯动画 */
@keyframes breathe {
0% { box-shadow: 0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[0]}; }
33% { box-shadow: 0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[1]}; }
66% { box-shadow: 0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[2]}; }
100% { box-shadow: 0 0 ${CONFIG.glowSize}px ${CONFIG.glowSize}px ${CONFIG.breatheColors[0]}; }
}
`;
document.head.appendChild(styleSheet);
// ====== 功能函数 ======
/**
* 创建浮动按钮元素
* @returns {HTMLImageElement} 创建的按钮元素
*/
function createFloatingButton() {
const btn = document.createElement('img');
btn.src = CONFIG.imageUrl;
btn.className = 'floating-button';
btn.style.cssText = `
right: ${CONFIG.buttonRight};
bottom: ${CONFIG.buttonBottom};
width: ${CONFIG.buttonSize}px;
height: ${CONFIG.buttonSize}px;
opacity: ${CONFIG.opacity};
animation: breathe ${CONFIG.breatheDuration}s infinite;
`;
return btn;
}
/**
* 创建单个解析源列表项
* @param {Array} item - 解析源配置项 [url, name]
* @returns {HTMLDivElement} 列表项元素
*/
function createSourceListItem([url, name]) {
const item = document.createElement('div');
item.className = 'source-item';
item.textContent = name;
item.style.color = url === CONFIG.parseUrl ? '#ECECEC' : '#00000099'; /* 列表选中和字体颜色 */
// 鼠标悬停效果
item.addEventListener('mouseenter', () =>
item.style.background = '#f5f5f525'); /* 鼠标悬停背景色 */
item.addEventListener('mouseleave', () =>
item.style.background = '');
// 点击处理
item.addEventListener('click', (e) => {
e.stopPropagation();
CONFIG.parseUrl = url;
GM_setValue('selectedParseUrl', url);
document.getElementById('parse-source-list')?.remove();
floatingButton.style.boxShadow =
`0 0 6px 6px ${CONFIG.breatheColors[0]}`;
});
return item;
}
/**
* 创建解析源选择列表
*/
function createSourceList() {
const existingList = document.getElementById('parse-source-list');
if (existingList) existingList.remove();
const list = document.createElement('div');
list.id = 'parse-source-list';
list.className = 'source-list';
list.style.cssText = `
right: ${CONFIG.buttonRight};
bottom: calc(${CONFIG.buttonBottom} + ${CONFIG.buttonSize + 10}px);
`;
// 添加所有解析源项
CONFIG.parseUrls.forEach(item =>
list.appendChild(createSourceListItem(item)));
// 点击外部关闭列表
const closeHandler = e => {
if (!list.contains(e.target) && e.target !== floatingButton) {
list.remove();
document.removeEventListener('click', closeHandler);
}
};
document.addEventListener('click', closeHandler);
return list;
}
/**
* 初始化浮动按钮交互事件
*/
function initButtonEvents() {
// 鼠标悬停效果
floatingButton.addEventListener('mouseenter', () => {
floatingButton.style.opacity = '1';
floatingButton.style.transform = 'scale(1.1)';
});
floatingButton.addEventListener('mouseleave', () => {
floatingButton.style.opacity = CONFIG.opacity;
floatingButton.style.transform = 'none';
});
// 单击/双击处理
floatingButton.addEventListener('click', () => {
clearTimeout(clickTimer);
clickTimer = setTimeout(() =>
window.open(CONFIG.parseUrl + location.href), 300);
});
floatingButton.addEventListener('dblclick', () => {
clearTimeout(clickTimer);
document.body.appendChild(createSourceList());
});
}
// ====== 主初始化函数 ======
function init() {
// 创建并插入浮动按钮
floatingButton = createFloatingButton();
document.body.appendChild(floatingButton);
// 初始化事件监听
initButtonEvents();
}
// ====== 启动脚本 ======
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();