https://www.dmmbus.cyou/forum/forum.php?mod=viewthread&tid=138391&extra=
这个插件功能包括:
(1)会将javbus网站上本地已经有(搜刮好的)的电影给标记出来
(2)查看javbus网站上下载链接里面视频截图(可以看出这个视频有没有广告,有没有字幕)
关于这个插件是干什么的以及怎么使用详情请见上面这个帖子上↑↑↑↑↑↑↑
这次2.0增加了功能,增加了一个预览磁力链接里面视频图片的功能有啥用:可以看出这个视频有没有广告,有没有字幕
改进:
以前扫描本地视频功能中改进了一下,改成了根据.nfo文件所在目录作为关键字(无论是我写搜刮软件以及mdcx都可以兼容了),考虑到了仓库可能是多个磁盘的情况
以下两个图片是第二个功能的使用情况,


这次代码有点多,因为第二个功能我是使用ai写的,你可以下滑到最下面,点击左下角的复制按钮
// ==UserScript==
// @name 仓鼠小助手
// @version 2.0.0
// @author 佚名
// @description 这是一个仓鼠助手
// @license MIT
// @icon https://www.javbus.com/favicon.ico
// @match *://*.javbus.com/*
// @match *://*.dmmbus.cyou/*
// @match *://*.busjav.cyou/*
// @match *://*.cdnbus.bond/*
// @match *://*.busdmm.bond/*
// ==/UserScript==
(function () {
'use strict';
// ========== 新增:弹窗样式 ==========
function createModalStyle() {
const style = document.createElement('style');
style.textContent = `
/* 弹窗遮罩层 */
.hamster-modal-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 99999;
display: none;
}
/* 弹窗主体 */
.hamster-modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 800px; /* 加宽弹窗以容纳图片 */
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
z-index: 100000;
display: none;
font-family: Arial, sans-serif;
overflow: hidden;
}
/* 弹窗头部 */
.hamster-modal-header {
padding: 15px 20px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
background: #f8f9fa;
border-radius: 8px 8px 0 0;
}
.hamster-modal-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 0;
}
.hamster-modal-close {
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
cursor: pointer;
font-size: 20px;
color: #666;
border: none;
background: transparent;
padding: 0;
}
.hamster-modal-close:hover {
color: #ff4444;
}
/* 弹窗内容 */
.hamster-modal-body {
padding: 20px;
max-height: 600px; /* 增高内容区 */
overflow-y: auto;
}
.hamster-info-item {
margin-bottom: 12px;
display: flex;
align-items: flex-start;
}
.hamster-info-label {
width: 80px;
font-weight: bold;
color: #666;
flex-shrink: 0;
padding-top: 2px;
}
.hamster-info-value {
flex: 1;
color: #333;
word-break: break-all;
line-height: 1.4;
}
.hamster-magnet-link {
color: #1976d2;
text-decoration: none;
}
.hamster-magnet-link:hover {
text-decoration: underline;
}
/* 轮播图区域 */
.hamster-carousel-section {
margin-top: 20px;
padding-top: 20px;
border-top: 1px dashed #ddd;
}
.hamster-carousel-title {
font-size: 14px;
font-weight: bold;
color: #666;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.hamster-carousel-counter {
font-size: 12px;
font-weight: normal;
color: #999;
}
/* 轮播图容器 */
.hamster-carousel {
position: relative;
width: 100%;
min-height: 100px;
background: #f5f5f5;
border-radius: 4px;
padding: 10px;
overflow: hidden;
}
/* 轮播图图片容器 */
.hamster-carousel-wrapper {
display: flex;
transition: transform 0.3s ease;
height: 300px; /* 固定轮播图高度 */
}
.hamster-carousel-item {
flex: 0 0 100%;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.hamster-carousel-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* 轮播图控制按钮 */
.hamster-carousel-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(0,0,0,0.5);
color: white;
border: none;
cursor: pointer;
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
transition: background 0.2s;
}
.hamster-carousel-btn:hover {
background: rgba(0,0,0,0.7);
}
.hamster-carousel-prev {
left: 10px;
}
.hamster-carousel-next {
right: 10px;
}
/* 轮播图指示器 */
.hamster-carousel-indicators {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
z-index: 10;
}
.hamster-carousel-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255,255,255,0.5);
cursor: pointer;
transition: background 0.2s;
}
.hamster-carousel-dot.active {
background: white;
width: 20px;
border-radius: 4px;
}
/* 轮播图状态提示 */
.hamster-carousel-loading,
.hamster-carousel-error {
color: #999;
font-size: 14px;
text-align: center;
padding: 20px;
width: 100%;
}
.hamster-carousel-error {
color: #ff4444;
}
/* 弹窗底部 */
.hamster-modal-footer {
padding: 12px 20px;
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 10px;
background: #f8f9fa;
border-radius: 0 0 8px 8px;
}
.hamster-modal-btn {
padding: 6px 16px;
border-radius: 4px;
border: none;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.hamster-copy-btn {
background: #2196f3;
color: white;
}
.hamster-copy-btn:hover {
background: #1976d2;
}
.hamster-close-btn {
background: #e0e0e0;
color: #333;
}
.hamster-close-btn:hover {
background: #d0d0d0;
}
/* 复制提示 */
.hamster-copy-tip {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 16px;
border-radius: 4px;
z-index: 100001;
display: none;
font-size: 14px;
}
/* 详情按钮列样式 */
.detail-btn-cell {
text-align: center;
white-space: nowrap;
width: 80px;
}
/* 柔和版详情按钮样式 */
.detail-btn {
border: none;
background: #f5f5f5;
color: #666;
padding: 4px 10px;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
transition: background 0.2s;
}
.detail-btn:hover {
background: #e9e9e9;
color: #128a34;
}
`;
document.head.appendChild(style);
}
// ========== 新增:创建弹窗DOM ==========
function createModalDOM() {
// 遮罩层
const mask = document.createElement('div');
mask.className = 'hamster-modal-mask';
mask.id = 'hamsterModalMask';
// 弹窗主体
const modal = document.createElement('div');
modal.className = 'hamster-modal';
modal.id = 'hamsterModal';
// 弹窗头部
const header = document.createElement('div');
header.className = 'hamster-modal-header';
const title = document.createElement('h3');
title.className = 'hamster-modal-title';
title.textContent = '磁力链接详情';
const closeBtn = document.createElement('button');
closeBtn.className = 'hamster-modal-close';
closeBtn.innerHTML = '×';
closeBtn.title = '关闭';
header.appendChild(title);
header.appendChild(closeBtn);
// 弹窗内容 - 移除了行号和磁力名称字段
const body = document.createElement('div');
body.className = 'hamster-modal-body';
body.innerHTML = `
<div class="hamster-info-item">
<div class="hamster-info-label">文件大小:</div>
<div class="hamster-info-value" id="modalSize"></div>
</div>
<div class="hamster-info-item">
<div class="hamster-info-label">分享日期:</div>
<div class="hamster-info-value" id="modalDate"></div>
</div>
<div class="hamster-info-item">
<div class="hamster-info-label">磁力链接:</div>
<div class="hamster-info-value">
<a class="hamster-magnet-link" id="modalMagnet" target="_self"></a>
</div>
</div>
<!-- 轮播图区域 -->
<div class="hamster-carousel-section">
<div class="hamster-carousel-title">
<span>预览图片</span>
<span class="hamster-carousel-counter" id="carouselCounter">0/0</span>
</div>
<div class="hamster-carousel" id="carouselContainer">
<div class="hamster-carousel-loading">加载预览图片中...</div>
<!-- 轮播图内容会动态生成 -->
</div>
</div>
`;
// 弹窗底部
const footer = document.createElement('div');
footer.className = 'hamster-modal-footer';
const copyBtn = document.createElement('button');
copyBtn.className = 'hamster-modal-btn hamster-copy-btn';
copyBtn.textContent = '复制链接';
copyBtn.id = 'hamsterCopyBtn';
const closeBtn2 = document.createElement('button');
closeBtn2.className = 'hamster-modal-btn hamster-close-btn';
closeBtn2.textContent = '关闭';
closeBtn2.id = 'hamsterCloseBtn';
footer.appendChild(copyBtn);
footer.appendChild(closeBtn2);
// 组装弹窗
modal.appendChild(header);
modal.appendChild(body);
modal.appendChild(footer);
// 复制提示
const copyTip = document.createElement('div');
copyTip.className = 'hamster-copy-tip';
copyTip.id = 'hamsterCopyTip';
copyTip.textContent = '复制成功!';
// 添加到页面
document.body.appendChild(mask);
document.body.appendChild(modal);
document.body.appendChild(copyTip);
// 绑定关闭事件
mask.addEventListener('click', hideModal);
closeBtn.addEventListener('click', hideModal);
closeBtn2.addEventListener('click', hideModal);
// 绑定复制事件
copyBtn.addEventListener('click', function () {
const magnetLink = document.getElementById('modalMagnet').href;
if (magnetLink) {
navigator.clipboard.writeText(magnetLink)
.then(() => {
const tip = document.getElementById('hamsterCopyTip');
tip.style.display = 'block';
setTimeout(() => {
tip.style.display = 'none';
}, 1500);
})
.catch(err => {
alert('复制失败:' + err.message);
});
}
});
// ESC键关闭弹窗
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
hideModal();
}
});
}
// ========== 轮播图控制函数 ==========
function initCarousel(images) {
const carouselContainer = document.getElementById('carouselContainer');
const counterEl = document.getElementById('carouselCounter');
let currentIndex = 0;
// 清空容器
carouselContainer.innerHTML = '';
// 更新计数器
counterEl.textContent = `${currentIndex + 1}/${images.length}`;
// 创建轮播图包装器
const wrapper = document.createElement('div');
wrapper.className = 'hamster-carousel-wrapper';
// 创建所有图片项
images.forEach((imgUrl, index) => {
const item = document.createElement('div');
item.className = 'hamster-carousel-item';
const img = document.createElement('img');
img.className = 'hamster-carousel-image';
img.src = imgUrl;
img.alt = `预览图片 ${index + 1}`;
// 图片加载失败处理
img.onerror = function () {
img.alt = `图片 ${index + 1} 加载失败`;
img.style.display = 'none';
item.innerHTML = `<div class="hamster-carousel-error">图片 ${index + 1} 加载失败</div>`;
};
item.appendChild(img);
wrapper.appendChild(item);
});
// 创建控制按钮
const prevBtn = document.createElement('button');
prevBtn.className = 'hamster-carousel-btn hamster-carousel-prev';
prevBtn.innerHTML = '<';
prevBtn.addEventListener('click', () => {
currentIndex = (currentIndex - 1 + images.length) % images.length;
updateCarousel();
});
const nextBtn = document.createElement('button');
nextBtn.className = 'hamster-carousel-btn hamster-carousel-next';
nextBtn.innerHTML = '>';
nextBtn.addEventListener('click', () => {
currentIndex = (currentIndex + 1) % images.length;
updateCarousel();
});
// 创建指示器
const indicators = document.createElement('div');
indicators.className = 'hamster-carousel-indicators';
images.forEach((_, index) => {
const dot = document.createElement('div');
dot.className = `hamster-carousel-dot ${index === currentIndex ? 'active' : ''}`;
dot.addEventListener('click', () => {
currentIndex = index;
updateCarousel();
});
indicators.appendChild(dot);
});
// 组装轮播图
carouselContainer.appendChild(wrapper);
carouselContainer.appendChild(prevBtn);
carouselContainer.appendChild(nextBtn);
carouselContainer.appendChild(indicators);
// 更新轮播图状态
function updateCarousel() {
// 移动图片容器
wrapper.style.transform = `translateX(-${currentIndex * 100}%)`;
// 更新计数器
counterEl.textContent = `${currentIndex + 1}/${images.length}`;
// 更新指示器
const dots = indicators.querySelectorAll('.hamster-carousel-dot');
dots.forEach((dot, index) => {
dot.className = `hamster-carousel-dot ${index === currentIndex ? 'active' : ''}`;
});
}
}
// ========== 显示/隐藏弹窗函数 ==========
async function showModal(row, magnetLink, rowElement) {
// 获取行数据(不再使用行号和磁力名称)
const size = rowElement.find('td:nth-child(3) a').text().trim() || '无'; // 列索引适配
const date = rowElement.find('td:nth-child(4) a').text().trim() || '无'; // 列索引适配
// 填充基础数据(移除了行号和磁力名称的赋值)
document.getElementById('modalSize').textContent = size;
document.getElementById('modalDate').textContent = date;
document.getElementById('modalMagnet').href = magnetLink;
document.getElementById('modalMagnet').textContent = magnetLink;
// 重置轮播图容器为加载状态
const carouselContainer = document.getElementById('carouselContainer');
const counterEl = document.getElementById('carouselCounter');
carouselContainer.innerHTML = '<div class="hamster-carousel-loading">加载预览图片中...</div>';
counterEl.textContent = '0/0';
// 显示弹窗
document.getElementById('hamsterModalMask').style.display = 'block';
document.getElementById('hamsterModal').style.display = 'block';
// 加载预览图片(轮播图版)
try {
const resp = await fetch('https://whatslink.info/api/v1/link?url=' + encodeURIComponent(magnetLink));
if (!resp.ok) throw new Error(`HTTP错误:${resp.status}`);
const json = await resp.json();
if (json.screenshots && json.screenshots.length > 0) {
// 提取所有图片URL
const imageUrls = json.screenshots.map(item => item.screenshot);
// 初始化轮播图
initCarousel(imageUrls);
} else {
carouselContainer.innerHTML = '<div class="hamster-carousel-error">暂无预览图片</div>';
}
} catch (err) {
console.error('加载预览图片失败:', err);
carouselContainer.innerHTML = `<div class="hamster-carousel-error">获取图片失败:${err.message}</div>`;
}
}
function hideModal() {
document.getElementById('hamsterModalMask').style.display = 'none';
document.getElementById('hamsterModal').style.display = 'none';
// 隐藏时重置轮播图
const carouselContainer = document.getElementById('carouselContainer');
const counterEl = document.getElementById('carouselCounter');
if (carouselContainer && counterEl) {
carouselContainer.innerHTML = '<div class="hamster-carousel-loading">加载预览图片中...</div>';
counterEl.textContent = '0/0';
}
}
// 创建一个按钮元素
let button = document.createElement('button');
button.innerHTML = '仓';
button.style.position = 'fixed';
button.style.bottom = '1px';
button.style.left = '1px';
button.style.zIndex = '1000';
button.style.alignContent = "center";
button.style.width = "35px";
button.style.height = "35px";
// 添加按钮点击事件
button.addEventListener('click', async function () {
button.style.background = "#aaaaff";
button.innerHTML = "....";
try {
await btnClick();
} catch (e) {
console.log('出错了', e);
alert('加载出错:' + e);
} finally {
button.style.background = "";
button.innerHTML = "仓"
}
});
// 将按钮添加到页面中
document.body.appendChild(button);
let dian = 1;//进度
async function btnClick() {
const nfoFilesSet = new Set();
const dirHandle = await window.showDirectoryPicker();
if (!dirHandle) {
alert("获取本地信息失败");
return;
}
async function scanDirectory(handle) {
for await (const entry of handle.values()) {
dian++;
button.innerHTML = "...".substring((dian % 3));
if (entry.kind === 'directory') {
// 1. 如果是文件夹,先递归检查该文件夹内部
await scanDirectory(entry);
} else if (entry.kind === 'file') {
// 2. 如果是文件,判断后缀是否为 .nfo
if (entry.name.toLowerCase().endsWith('.nfo')) {
// 3. 将包含该文件的父级文件夹名称存入 Set
nfoFilesSet.add(handle.name);
}
}
}
}
// 执行遍历
await scanDirectory(dirHandle);
const oldFilesStr = localStorage.getItem("nfoFiles");
const oldFiles = JSON.parse(oldFilesStr || '[]');
for (const name of oldFiles) {
nfoFilesSet.add(name);
}
const str = JSON.stringify(Array.from(nfoFilesSet));
localStorage.setItem("nfoFiles", str);
console.log("设置成功,数量", oldFiles.length, '->', nfoFilesSet.size);
start();
}
async function start() {
const nfoFilesStr = localStorage.getItem('nfoFiles');
if (!nfoFilesStr) {
return;
}
const nfoFiles = JSON.parse(nfoFilesStr);
console.log('共加载', nfoFiles.length, "个");
$('#waterfall .movie-box').each((index, ele) => {
var movieBox = $(ele);
const url = movieBox.attr('href');
const code = url.substring(url.lastIndexOf('/') + 1);
if (nfoFiles.indexOf(code) != -1) {
movieBox.css('background-color', 'red');
}
})
const url = location.href;
const code = url.substring(url.lastIndexOf('/') + 1);
if (nfoFiles.indexOf(code) != -1) {
$('div.row.movie').css('background-color', 'gold')
}
}
start();
async function linkInfo(loaded) {
const mt = $('#magnet-table');
if (!mt.length) {
return;
}
if ($('#magnet-table tr').length > 1) {
loaded = true;
}
if (!loaded) {
const observer = new MutationObserver(function (mutations) {
// 遍历所有DOM变化
mutations.forEach(function (mutation) {
// 只处理"子节点添加/移除"的变化
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
// 延迟50ms执行(确保动态行完全加载)
observer.disconnect();
setTimeout(() => {
linkInfo(true)
}, 50);
}
});
});
// 配置监听选项:监听tbody的子节点变化、子节点的子节点变化
const observerConfig = {
childList: true, // 监听子节点添加/移除
subtree: true, // 监听子树(行内的td变化)
attributes: false // 不监听属性变化(可根据需要开启)
};
// 启动监听:监听表格tbody的变化
const targetNode = document.querySelector('#magnet-table');
if (targetNode) {
observer.observe(targetNode, observerConfig);
}
return;
}
// 初始化弹窗样式和DOM
createModalStyle();
createModalDOM();
// 1. 给表头新增"详情"列(第一列)
const $headerRow = $('#magnet-table tbody tr:first');
if ($headerRow.find('td').length >= 3) { // 确保表头存在
// 在表头第一个位置插入详情列
$headerRow.prepend('<td class="detail-btn-cell" style="text-align:center;white-space:nowrap">详情</td>');
}
// 2. 给每一行数据新增详情按钮列(第一列)
$('#magnet-table tr:not(:first)').each(function (index) {
const $row = $(this);
// 检查是否已经添加过详情按钮(防止重复)
if ($row.find('td').length >= 3 && !$row.find('.detail-btn-cell').length) {
// 获取当前行的磁力链接(原第二列变为第三列)
var magnetLink = $row.find('td:nth-child(2) a').attr('href'); // 列索引适配
var rowIndex = index + 1; // 行号(从1开始)
// 构建柔和版详情按钮的HTML(仅显示"详情"二字,无图标)
var detailBtn = `
<td class="detail-btn-cell">
<button class="detail-btn"
data-magnet="${magnetLink}"
data-row="${rowIndex}">
详情
</button>
</td>
`;
// 将按钮添加到当前行的第一个位置
$row.prepend(detailBtn);
}
});
// 3. 给详情按钮绑定点击事件(使用事件委托防止重复绑定)
$('#magnet-table').off('click', '.detail-btn').on('click', '.detail-btn', function () {
var magnet = $(this).data('magnet'); // 获取磁力链接
var row = $(this).data('row'); // 行号仍保留(内部使用,不显示)
var $rowElement = $(this).closest('tr'); // 获取当前行元素
// 显示自定义弹窗
showModal(row, magnet, $rowElement);
});
}
linkInfo();
})();複製代碼
还没有评论,来抢沙发吧。