// ==UserScript==
// @name 网页复制限制解除
// @namespace http://tampermonkey.net/
// @version 1.4
// @description 解除网站复制限制、去除复制水印
// @author Heavrnl
// @license MIT
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// ==/UserScript==
(function () {
'use strict';
// 检查是否在 iframe 中
const isInIframe = window !== window.top;
// 添加设置界面的样式
GM_addStyle(`
.watermark-settings {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
z-index: 10000;
width: 500px;
font-family: Arial, sans-serif;
}
.watermark-settings h2 {
margin: 0 0 15px 0;
color: #333;
}
.watermark-settings .buttons {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.watermark-settings button {
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.watermark-settings .save {
background: #28a745;
color: white;
}
.watermark-settings .cancel {
background: #dc3545;
color: white;
}
.watermark-settings .overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 9999;
}
`);
// 初始化设置 - 只在主页面中执行
if (!isInIframe) {
if (GM_getValue('watermarkSites') === undefined) {
GM_setValue('watermarkSites', {}); // 使用对象存储各网站的去水印状态
}
if (GM_getValue('copySites') === undefined) {
GM_setValue('copySites', {}); // 使用对象存储各网站的复制解除状态
}
}
// 检查当前网站的复制解除状态
const isCopyEnabled = () => {
const currentHost = window.location.hostname;
const copySites = GM_getValue('copySites', {});
return copySites[currentHost] || false;
};
// 修改去水印功能
function removeWatermark() {
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
if (!watermarkSites[currentHost]) return;
document.addEventListener('copy', function(e) {
e.stopPropagation();
const selection = window.getSelection();
e.clipboardData.setData('text/plain', selection.toString());
e.preventDefault();
}, true);
}
// 创建并添加按钮
const button = document.createElement("button");
// 使用 SVG 图标替代文字
const svgIcon = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
</svg>`;
button.innerHTML = svgIcon;
// 根据存储的状态设置按钮样式
const isEnabled = GM_getValue('enableCopyRemoval', false);
const getButtonStyle = (enabled) => `
position: fixed;
right: 10px;
bottom: 15%;
z-index: 9999;
width: 32px;
height: 32px;
padding: 6px;
background-color: ${enabled ? 'rgba(220, 53, 69, 0.3)' : 'rgba(40, 167, 69, 0.3)'};
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.3;
`;
button.style.cssText = getButtonStyle(isEnabled);
// 悬停效果
button.onmouseenter = () => {
button.style.opacity = "1";
const currentHost = window.location.hostname;
const copySites = GM_getValue('copySites', {});
const isEnabled = copySites[currentHost] || false;
button.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.9)' :
'rgba(40, 167, 69, 0.9)';
};
button.onmouseleave = () => {
button.style.opacity = "0.3";
const currentHost = window.location.hostname;
const copySites = GM_getValue('copySites', {});
const isEnabled = copySites[currentHost] || false;
button.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.3)' :
'rgba(40, 167, 69, 0.3)';
};
document.body.appendChild(button);
// 修改点击按钮时切换状态的代码
const handleButtonClick = () => {
const currentHost = window.location.hostname;
const copySites = GM_getValue('copySites', {});
const currentState = copySites[currentHost] || false;
if (!currentState) {
// 启用当前网站的复制解除
copySites[currentHost] = true;
GM_setValue('copySites', copySites);
// 立即启用复制解除
enableCopyAndRemoveOverlay();
// 更新按钮样式
button.style.backgroundColor = 'rgba(220, 53, 69, 0.3)';
// 立即应用额外的复制解除措施
const style = document.createElement('style');
style.innerHTML = `
* {
-webkit-user-select: text !important;
-moz-user-select: text !important;
-ms-user-select: text !important;
user-select: text !important;
-webkit-touch-callout: default !important;
}
::selection {
background-color: #338FFF !important;
color: #fff !important;
}
`;
document.head.appendChild(style);
// 立即移除所有元素的复制限制
document.querySelectorAll('*').forEach(element => {
element.style.userSelect = "text";
element.style.webkitUserSelect = "text";
element.style.msUserSelect = "text";
element.style.MozUserSelect = "text";
// 移除事件监听器
element.oncontextmenu = null;
element.onselectstart = null;
element.onselect = null;
element.oncopy = null;
element.onbeforecopy = null;
element.oncut = null;
element.onpaste = null;
element.ondrag = null;
element.ondragstart = null;
});
// 立即覆盖文档级别的事件
document.oncontextmenu = null;
document.onselectstart = null;
document.oncopy = null;
document.oncut = null;
document.onpaste = null;
// 添加复制事件监听器
document.addEventListener('copy', function(e) {
e.stopPropagation();
const selection = window.getSelection();
e.clipboardData.setData('text/plain', selection.toString());
}, true);
} else {
// 禁用当前网站的复制解除
copySites[currentHost] = false;
GM_setValue('copySites', copySites);
location.reload(); // 刷新页面以恢复原始状态
}
};
// 绑定点击事件
button.addEventListener("click", handleButtonClick);
// 移除复制限制及遮挡层的功能
const enableCopyAndRemoveOverlay = () => {
const currentHost = window.location.hostname;
const copySites = GM_getValue('copySites', {});
if (!copySites[currentHost]) return;
// 处理CSDN特定的复制限制
document.querySelectorAll('*').forEach(element => {
// 移除CSDN特定的user-select限制
if (element.classList.contains('htmledit_views') ||
element.classList.contains('markdown_views') ||
element.classList.contains('article_content')) {
element.style.cssText = `
-webkit-user-select: text !important;
-moz-user-select: text !important;
-ms-user-select: text !important;
user-select: text !important;
`;
}
// 移除CSDN的事件监听器
element.oncontextmenu = null;
element.onselectstart = null;
element.onselect = null;
element.oncopy = null;
element.onbeforecopy = null;
element.oncut = null;
element.onpaste = null;
element.ondrag = null;
element.ondragstart = null;
});
// 覆盖CSDN的复制事件处理
document.addEventListener('copy', function(e) {
e.stopPropagation();
const selection = window.getSelection();
e.clipboardData.setData('text/plain', selection.toString());
}, true);
// 移除CSDN的遮罩层和弹窗
const removeOverlays = () => {
const overlays = document.querySelectorAll('.login-mark, .login-box');
overlays.forEach(overlay => overlay.remove());
};
// 定期检查并移除遮罩
setInterval(removeOverlays, 100);
// 移除所有元素的复制限制
document.querySelectorAll('*').forEach(element => {
// 允许选择文本
element.style.userSelect = "text";
element.style.webkitUserSelect = "text";
element.style.msUserSelect = "text";
element.style.MozUserSelect = "text";
// 移除事件监听器
element.onselectstart = null;
element.oncontextmenu = null;
element.onmousedown = null;
element.onkeydown = null;
element.oncopy = null;
element.oncut = null;
element.ondrag = null;
element.ondragstart = null;
// 移除 unselectable 属性
element.removeAttribute('unselectable');
element.removeAttribute('oncontextmenu');
element.removeAttribute('oncopy');
element.removeAttribute('oncut');
element.removeAttribute('onselectstart');
});
// 移除遮挡层
document.querySelectorAll('*').forEach(element => {
const style = window.getComputedStyle(element);
if ((style.position === 'absolute' || style.position === 'fixed') &&
(style.opacity === '0' || parseFloat(style.opacity) < 0.1) &&
style.zIndex > 0) {
element.remove();
}
});
// 覆盖常见的禁用右键和复制的方法
document.oncontextmenu = null;
document.onselectstart = null;
document.oncopy = null;
document.oncut = null;
document.onpaste = null;
document.onkeydown = null;
document.onmousedown = null;
// 覆盖 window 对象上的限制方法
window.oncontextmenu = null;
window.onselectstart = null;
window.oncopy = null;
window.oncut = null;
window.onpaste = null;
window.onkeydown = null;
window.onmousedown = null;
// 阻止页面使用 addEventListener 添加新的限制
const originalAddEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener, options) {
if (type === 'contextmenu' || type === 'selectstart' ||
type === 'copy' || type === 'cut' || type === 'paste' ||
type === 'keydown' || type === 'mousedown') {
return;
}
originalAddEventListener.call(this, type, listener, options);
};
// 移除 CSS 限制
const style = document.createElement('style');
style.innerHTML = `
* {
-webkit-user-select: text !important;
-moz-user-select: text !important;
-ms-user-select: text !important;
user-select: text !important;
-webkit-touch-callout: default !important;
}
::selection {
background-color: #338FFF !important;
color: #fff !important;
}
`;
document.head.appendChild(style);
// 添加百度文库的特殊处理
if (location.hostname.includes('wenku.baidu.com')) {
// 移除文字选择限制
document.querySelectorAll('.reader-word-layer').forEach(element => {
element.style.userSelect = 'text';
element.style.webkitUserSelect = 'text';
element.style.MozUserSelect = 'text';
element.style.msUserSelect = 'text';
});
// 移除复制拦截
document.addEventListener('copy', function(e) {
e.stopPropagation();
const selection = window.getSelection();
e.clipboardData.setData('text/plain', selection.toString());
}, true);
// 移除CSS档遮罩
const removeWenkuOverlay = () => {
const overlays = document.querySelectorAll('.reader-mask, .vip-pop-wrap, .show-pay-modal, .payment-modal-wrap');
overlays.forEach(overlay => overlay.remove());
};
// 定期检查并移除遮罩
setInterval(removeWenkuOverlay, 500);
// 修改文档容器样式
const readerContainer = document.querySelector('.reader-container');
if (readerContainer) {
readerContainer.style.height = 'auto';
readerContainer.style.overflow = 'visible';
}
}
};
// 修改 MutationObserver,只在功能开启时才观察
const observer = new MutationObserver(() => {
if (GM_getValue('enableCopyRemoval', false)) {
enableCopyAndRemoveOverlay();
}
});
observer.observe(document.body, { childList: true, subtree: true });
// 创建并添加去水印按钮
const watermarkButton = document.createElement("button");
const watermarkSvgIcon = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="1" y1="1" x2="23" y2="23"></line>
<path d="M21 21H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2z"></path>
</svg>`;
watermarkButton.innerHTML = watermarkSvgIcon;
// 获取去水印功能的状态
const isWatermarkEnabled = () => {
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
return watermarkSites[currentHost] || false;
};
// 设置去水印按钮样式
const getWatermarkButtonStyle = (enabled) => `
position: fixed;
right: 10px;
bottom: 10%;
z-index: 9999;
width: 32px;
height: 32px;
padding: 6px;
background-color: ${enabled ? 'rgba(220, 53, 69, 0.3)' : 'rgba(40, 167, 69, 0.3)'};
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.3;
`;
watermarkButton.style.cssText = getWatermarkButtonStyle(isWatermarkEnabled());
// 去水印按钮的悬停效果
watermarkButton.onmouseenter = () => {
watermarkButton.style.opacity = "1";
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
const isEnabled = watermarkSites[currentHost] || false;
watermarkButton.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.9)' :
'rgba(40, 167, 69, 0.9)';
};
watermarkButton.onmouseleave = () => {
watermarkButton.style.opacity = "0.3";
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
const isEnabled = watermarkSites[currentHost] || false;
watermarkButton.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.3)' :
'rgba(40, 167, 69, 0.3)';
};
// 去水印按钮点击事件
watermarkButton.addEventListener("click", () => {
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
const currentState = watermarkSites[currentHost] || false;
watermarkSites[currentHost] = !currentState;
GM_setValue('watermarkSites', watermarkSites);
// 立即应用新状态
if (!currentState) {
removeWatermark();
} else {
location.reload(); // 如果是关闭状态,需要刷新页面
}
// 更新按钮样式
watermarkButton.style.cssText = getWatermarkButtonStyle(!currentState);
});
document.body.appendChild(watermarkButton);
// 添加按钮组样式
GM_addStyle(`
.float-button-group {
position: fixed;
right: 10px;
bottom: 15%;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 8px;
}
.float-button {
width: 32px;
height: 32px;
padding: 6px;
background-color: rgba(40, 167, 69, 0.3);
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.3;
}
`);
// 创建按钮组容器
const buttonGroup = document.createElement('div');
buttonGroup.className = 'float-button-group';
// 创建复制解除按钮
const copyButton = document.createElement("button");
copyButton.className = 'float-button';
copyButton.innerHTML = svgIcon;
// 创建去水印按钮
const watermarkBtn = document.createElement("button");
watermarkBtn.className = 'float-button';
watermarkBtn.innerHTML = watermarkSvgIcon;
// 更新按钮状态的函数
const updateButtonStyle = (btn, enabled) => {
btn.style.backgroundColor = enabled ?
'rgba(220, 53, 69, 0.3)' :
'rgba(40, 167, 69, 0.3)';
};
// 设置初始状态
const copyEnabled = isCopyEnabled();
updateButtonStyle(copyButton, copyEnabled);
const watermarkEnabled = isWatermarkEnabled();
updateButtonStyle(watermarkBtn, watermarkEnabled);
// 复制按钮的悬停效果
copyButton.onmouseenter = () => {
copyButton.style.opacity = "1";
const isEnabled = isCopyEnabled();
copyButton.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.9)' :
'rgba(40, 167, 69, 0.9)';
};
copyButton.onmouseleave = () => {
copyButton.style.opacity = "0.3";
const isEnabled = isCopyEnabled();
copyButton.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.3)' :
'rgba(40, 167, 69, 0.3)';
};
// 去水印按钮的悬停效果
watermarkBtn.onmouseenter = () => {
watermarkBtn.style.opacity = "1";
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
const isEnabled = watermarkSites[currentHost] || false;
watermarkBtn.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.9)' :
'rgba(40, 167, 69, 0.9)';
};
watermarkBtn.onmouseleave = () => {
watermarkBtn.style.opacity = "0.3";
const currentHost = window.location.hostname;
const watermarkSites = GM_getValue('watermarkSites', {});
const isEnabled = watermarkSites[currentHost] || false;
watermarkBtn.style.backgroundColor = isEnabled ?
'rgba(220, 53, 69, 0.3)' :
'rgba(40, 167, 69, 0.3)';
};
// 绑定点击事件
copyButton.addEventListener("click", handleButtonClick);
watermarkBtn.addEventListener("click", handleWatermarkButtonClick);
// 将按钮添加到按钮组
buttonGroup.appendChild(copyButton);
buttonGroup.appendChild(watermarkBtn);
// 将按钮组添加到页面
document.body.appendChild(buttonGroup);
// 移除之前直接添加到body的按钮
const oldButtons = document.querySelectorAll('button[style*="position: fixed"]');
oldButtons.forEach(btn => btn.remove());
})();