Greasy Fork is available in English.
夸克懒得点.. 修复误判,组合“头像Hash+昵称”进行精准屏蔽,并记录自动保存的日志(含网址)
当前为
// ==UserScript==
// @name 夸克懒得点 (屏蔽版+日志记录)
// @namespace http://greasyfork.icu/users/158417
// @version 0.22
// @description 夸克懒得点.. 修复误判,组合“头像Hash+昵称”进行精准屏蔽,并记录自动保存的日志(含网址)
// @author JIEMO
// @match *://pan.quark.cn/*
// @icon https://pan.quark.cn/favicon.ico
// @license GPL-3.0 License
// @run-at document-end
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_setClipboard
// ==/UserScript==
(function() {
'use strict';
// ================= 配置区域 =================
const STORAGE_KEY = "blocked_users_v2"; // 屏蔽列表键名
const LOG_KEY = "auto_save_logs"; // 日志存储键名
const MAX_LOGS = 200; // 最大保留日志条数
const DEFAULT_BLOCKED = [];
// ===========================================
// ============================================================
// 1. 基础工具
// ============================================================
function getBlockedList() {
return GM_getValue(STORAGE_KEY, DEFAULT_BLOCKED);
}
function setBlockedList(list) {
GM_setValue(STORAGE_KEY, list);
}
// 获取日志列表
function getLogs() {
return GM_getValue(LOG_KEY, []);
}
// 写入日志列表
function setLogs(list) {
GM_setValue(LOG_KEY, list);
}
// 格式化时间
function formatTime(date) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const h = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const s = String(date.getSeconds()).padStart(2, '0');
return `${y}-${m}-${d} ${h}:${min}:${s}`;
}
// 字符串转 Hash 算法
function computeStringHash(str) {
if (!str) return "null";
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0;
}
return "u" + Math.abs(hash);
}
// ============================================================
// 2. 核心逻辑:提取信息
// ============================================================
function getTargetSharerInfo() {
const shareContainer = document.querySelector('.share-info-wrap');
if (!shareContainer) return null;
const imgElement = shareContainer.querySelector('img');
if (!imgElement || !imgElement.src) return null;
const hashID = computeStringHash(imgElement.src);
const nameElement = shareContainer.querySelector('.author-name');
let nickName = "Unknown";
if (nameElement) {
nickName = nameElement.innerText.trim();
} else {
const possibleNames = shareContainer.querySelectorAll('div');
if(possibleNames.length > 1) {
nickName = possibleNames[1].innerText.trim();
}
}
return { name: nickName, hash: hashID };
}
function getFileTitle() {
const titleEl = document.querySelector('.filename-text');
if (titleEl) {
return titleEl.getAttribute('title') || titleEl.innerText.trim();
}
return document.title.replace(' - 夸克网盘', '') || "未知标题";
}
// ============================================================
// 3. 日志记录逻辑
// ============================================================
function recordLog(user) {
const fileName = getFileTitle();
const currentTime = formatTime(new Date());
const currentUrl = window.location.href;
const newLog = {
time: currentTime,
name: user.name,
hash: user.hash,
title: fileName,
url: currentUrl
};
let logs = getLogs();
logs.unshift(newLog); // 插入到最前面
if (logs.length > MAX_LOGS) {
logs = logs.slice(0, MAX_LOGS);
}
setLogs(logs);
console.log(`[夸克懒得点] 日志已记录: ${fileName}`);
}
// ============================================================
// 4. UI 交互 & 菜单
// ============================================================
function showBlockedOverlay(user) {
var overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.95)', zIndex: '999999',
display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'column'
});
var text = document.createElement('h1');
text.innerText = "⚠️ 已屏蔽该分享者";
text.style.cssText = "color: red; font-size: 60px; font-weight: bold; text-shadow: 2px 2px 10px black; margin: 0;";
var subText = document.createElement('div');
subText.innerHTML = `<p style='font-size:24px; color:white'>昵称:<span style='color:#ff6a00'>${user.name}</span></p>
<p style='font-size:16px; color:#888'>Hash:${user.hash}</p>`;
subText.style.textAlign = 'center';
subText.style.marginTop = '20px';
var unlockBtn = document.createElement('button');
unlockBtn.innerText = "本次临时允许 (点击消失)";
unlockBtn.style.cssText = "margin-top: 30px; padding: 10px 20px; cursor: pointer; background: #333; color: #fff; border: 1px solid #666;";
unlockBtn.onclick = function() { overlay.remove(); };
overlay.appendChild(text);
overlay.appendChild(subText);
overlay.appendChild(unlockBtn);
document.body.appendChild(overlay);
}
function showLogViewer() {
const logs = getLogs();
if (logs.length === 0) {
alert("暂无日志记录。");
return;
}
let logText = "时间\t\t\t昵称\t\t文件标题\t\t\t网址\n";
logText += "--------------------------------------------------------------------------------------\n";
logs.forEach(log => {
const u = log.url || "无记录";
logText += `[${log.time}] ${log.name} (${log.hash}) >>> ${log.title} >>> ${u}\n`;
});
var overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
backgroundColor: 'rgba(0,0,0,0.8)', zIndex: '999999',
display: 'flex', justifyContent: 'center', alignItems: 'center'
});
var box = document.createElement('div');
Object.assign(box.style, {
width: '85%', height: '85%', backgroundColor: '#fff', borderRadius: '8px',
padding: '20px', display: 'flex', flexDirection: 'column', color: '#333'
});
var title = document.createElement('h2');
title.innerText = `📜 自动保存日志 (最近 ${logs.length} 条)`;
title.style.margin = '0 0 10px 0';
var textarea = document.createElement('textarea');
textarea.value = logText;
Object.assign(textarea.style, {
flex: '1', width: '100%', fontSize: '12px', fontFamily: 'monospace',
whiteSpace: 'pre', overflow: 'auto', border: '1px solid #ccc', padding: '10px'
});
var btnContainer = document.createElement('div');
btnContainer.style.marginTop = '10px';
btnContainer.style.textAlign = 'right';
var copyBtn = document.createElement('button');
copyBtn.innerText = "复制到剪贴板";
copyBtn.style.marginRight = "10px";
copyBtn.onclick = function() {
GM_setClipboard(logText);
alert("✅ 已复制!");
};
var clearBtn = document.createElement('button');
clearBtn.innerText = "清空日志";
clearBtn.style.marginRight = "10px";
clearBtn.style.color = "red";
clearBtn.onclick = function() {
if(confirm("确定要清空所有日志吗?")) {
setLogs([]);
textarea.value = "";
}
};
var closeBtn = document.createElement('button');
closeBtn.innerText = "关闭";
closeBtn.onclick = function() { overlay.remove(); };
btnContainer.appendChild(clearBtn);
btnContainer.appendChild(copyBtn);
btnContainer.appendChild(closeBtn);
box.appendChild(title);
box.appendChild(textarea);
box.appendChild(btnContainer);
overlay.appendChild(box);
document.body.appendChild(overlay);
}
function registerMenus() {
GM_registerMenuCommand("🚫 屏蔽当前分享者", function() {
const currentUser = getTargetSharerInfo();
if (!currentUser) {
alert("❌ 无法定位信息,请确保页面加载完成。");
return;
}
const list = getBlockedList();
const exists = list.some(u => u.name === currentUser.name && u.hash === currentUser.hash);
if (exists) {
alert(`用户 [${currentUser.name}] 已存在。`);
} else {
list.push(currentUser);
setBlockedList(list);
if(confirm(`✅ 已屏蔽: ${currentUser.name}\n是否刷新生效?`)) location.reload();
}
});
GM_registerMenuCommand("⚙️ 管理屏蔽列表", function() {
const list = getBlockedList();
if (list.length === 0) {
alert("屏蔽列表为空。");
return;
}
let msg = "当前屏蔽列表:\n----------------------\n";
list.forEach((u, index) => {
msg += `【${index + 1}】 ${u.name} (Hash: ${u.hash})\n`;
});
const input = prompt(msg + "\n请输入序号删除:");
if (input) {
const index = parseInt(input) - 1;
if (!isNaN(index) && index >= 0 && index < list.length) {
list.splice(index, 1);
setBlockedList(list);
alert("✅ 已移除,刷新生效。");
location.reload();
}
}
});
GM_registerMenuCommand("📜 查看/导出保存日志", function() {
showLogViewer();
});
}
registerMenus();
// ============================================================
// 5. 主程序执行
// ============================================================
// 场景1:分享页面
if (window.location.href.startsWith("https://pan.quark.cn/s/")) {
window.onload = function() {
setTimeout(function() {
// --- 步骤 A: 获取当前分享者信息 ---
const currentUser = getTargetSharerInfo();
// --- 步骤 B: 检查屏蔽列表 ---
if (currentUser) {
const blockedList = getBlockedList();
const isBlocked = blockedList.some(u => u.name === currentUser.name && u.hash === currentUser.hash);
if (isBlocked) {
console.warn(`[夸克懒得点] 触发屏蔽!用户: ${currentUser.name}`);
showBlockedOverlay(currentUser);
return; // ⛔ 阻断
}
}
// --- 步骤 C: 自动转存 ---
console.log("[夸克懒得点] 检查通过,执行自动转存...");
// 1. 勾选文件
var checkboxElement = document.querySelector('.ant-checkbox-input');
try {
if (checkboxElement && !checkboxElement.checked) {
checkboxElement.click();
}
} catch (error) { console.error(error); }
// 2. 点击保存 (日志记录移到这里!)
var saveButtonElement = document.querySelector('.share-save');
if (saveButtonElement) {
if (currentUser) recordLog(currentUser); // ✅ 只有这里才记录
saveButtonElement.click();
} else {
var saveButtonElement2 = document.querySelector('.file-info_r');
if (saveButtonElement2) {
if (currentUser) recordLog(currentUser); // ✅ 备用按钮也记录
saveButtonElement2.click();
}
}
// 3. 确认与跳转
setTimeout(function() {
var confirmButtonElement = document.querySelector('.confirm-btn');
if (confirmButtonElement) {
confirmButtonElement.click();
}
var intervalId = setInterval(function() {
var viewButtonElement = document.querySelector('.path');
if (viewButtonElement) {
viewButtonElement.click();
clearInterval(intervalId);
}
}, 1000);
}, 1000);
}, 1500);
};
}
// 场景2:列表页面
if (window.location.href.startsWith("https://pan.quark.cn/list")) {
window.onload = function() {
setTimeout(function() {
var checkboxElement = document.querySelector('.ant-checkbox-wrapper');
try {
if(checkboxElement) checkboxElement.click();
} catch (error) {}
}, 1000);
};
}
})();