// ==UserScript==
// @name Zlib2WebDAV上传助手 发布版本
// @namespace http://tampermonkey.net/
// @version 1.1
// @description 在Z-lib网站的图书详情页 上传图书至WebDAV 可从脚本设置修改WebDAV设置
// @author StreamL
// @match https://zlib.by/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_notification
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
// 默认配置
const defaultConfig = {
webdav: {
endpoint: ' ',
id: ' ',
password: ' ',
directory: ''
}
};
// 获取配置
function getConfig() {
const saved = GM_getValue('webdav_config');
return saved ? JSON.parse(saved) : defaultConfig;
}
// 保存配置
function saveConfig(config) {
GM_setValue('webdav_config', JSON.stringify(config));
}
// 创建浮动按钮
function createFloatingButton() {
const buttonContainer = document.createElement('div');
buttonContainer.innerHTML = `
WebDAV
`;
document.body.appendChild(buttonContainer);
const btn = document.getElementById('webdav-btn');
// 添加悬停效果
btn.addEventListener('mouseenter', () => {
btn.style.background = '#0056b3';
btn.style.transform = 'translateY(-50%) scale(1.05)';
btn.style.boxShadow = '0 6px 16px rgba(0,123,255,0.4)';
});
btn.addEventListener('mouseleave', () => {
btn.style.background = '#007bff';
btn.style.transform = 'translateY(-50%) scale(1)';
btn.style.boxShadow = '0 4px 12px rgba(0,123,255,0.3)';
});
btn.addEventListener('click', handleButtonClick);
}
// 获取下载链接
function getDownloadLink() {
const selector = 'body > div.container > div > div > div:nth-child(4) > section > div > div.book-actions-buttons > div:nth-child(4) > div > a';
const downloadBtn = document.querySelector(selector);
return downloadBtn ? downloadBtn.href : null;
}
// 处理按钮点击
function handleButtonClick() {
const downloadUrl = getDownloadLink();
if (!downloadUrl) {
alert('未找到下载按钮');
return;
}
// 设置按钮为等待状态
setButtonLoading(true);
// 显示进度提示
showNotification(`正在请求 ${downloadUrl} 的内容...`);
// 发送请求获取文件
GM_xmlhttpRequest({
method: 'GET',
url: downloadUrl,
responseType: 'blob',
onload: function(response) {
setButtonLoading(false);
handleDownloadResponse(response);
},
onerror: function(error) {
setButtonLoading(false);
showNotification('下载失败: ' + error.statusText, 'error');
}
});
}
// 处理下载响应
function handleDownloadResponse(response) {
if (response.status === 200) {
// 尝试从响应头获取文件名
const contentDisposition = response.responseHeaders.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
let filename = '';
if (contentDisposition) {
filename = contentDisposition[1].replace(/['"]/g, '');
}
// 检查文件扩展名
const validExtensions = ['txt', 'epub', 'mobi', 'azw3', 'pdf'];
const fileExt = filename.split('.').pop().toLowerCase();
if (!validExtensions.includes(fileExt)) {
showNotification('无法获取有效的电子书文件', 'error');
return;
}
// 显示确认对话框
showConfirmDialog(filename, response.response);
} else {
showNotification('无法获取文件内容', 'error');
}
}
// 显示确认对话框
function showConfirmDialog(filename, fileBlob) {
const dialog = document.createElement('div');
dialog.innerHTML = `
确认上传
文件名: ${filename}
`;
document.body.appendChild(dialog);
// 添加按钮悬停效果
const cancelBtn = document.getElementById('cancel-btn');
const confirmBtn = document.getElementById('confirm-btn');
cancelBtn.addEventListener('mouseenter', () => {
cancelBtn.style.borderColor = '#bbb';
cancelBtn.style.color = '#333';
});
cancelBtn.addEventListener('mouseleave', () => {
cancelBtn.style.borderColor = '#ddd';
cancelBtn.style.color = '#666';
});
confirmBtn.addEventListener('mouseenter', () => {
confirmBtn.style.background = '#0056b3';
});
confirmBtn.addEventListener('mouseleave', () => {
confirmBtn.style.background = '#007bff';
});
// 绑定事件
cancelBtn.addEventListener('click', () => {
document.body.removeChild(dialog);
});
confirmBtn.addEventListener('click', () => {
document.body.removeChild(dialog);
uploadToWebDAV(filename, fileBlob);
});
}
// 上传到WebDAV
function uploadToWebDAV(filename, fileBlob) {
const config = getConfig();
const webdav = config.webdav;
const uploadUrl = webdav.endpoint + webdav.directory + filename;
// 设置按钮为等待状态
setButtonLoading(true);
showNotification('正在上传文件...');
GM_xmlhttpRequest({
method: 'PUT',
url: uploadUrl,
data: fileBlob,
headers: {
'Authorization': 'Basic ' + btoa(webdav.id + ':' + webdav.password)
},
onload: function(response) {
setButtonLoading(false);
if (response.status >= 200 && response.status < 300) {
showNotification('文件已成功上传到WebDAV', 'success');
} else {
showNotification('上传失败: ' + response.statusText, 'error');
}
},
onerror: function(error) {
setButtonLoading(false);
showNotification('上传错误: ' + error.statusText, 'error');
}
});
}
// 显示通知
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
const bgColor = type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#007bff';
notification.innerHTML = `
${message}
`;
document.body.appendChild(notification);
// 3秒后自动移除
setTimeout(() => {
if (notification.parentNode) {
document.body.removeChild(notification);
}
}, 3000);
}
// 显示设置对话框
function showSettingsDialog() {
const config = getConfig();
const dialog = document.createElement('div');
dialog.innerHTML = `
`;
document.body.appendChild(dialog);
// 添加输入框焦点效果
const inputs = dialog.querySelectorAll('input, textarea');
inputs.forEach(input => {
input.addEventListener('focus', () => {
input.style.borderColor = '#007bff';
input.style.boxShadow = '0 0 0 3px rgba(0,123,255,0.1)';
});
input.addEventListener('blur', () => {
input.style.borderColor = '#e1e5e9';
input.style.boxShadow = 'none';
});
});
// 绑定事件
document.getElementById('cancel-settings-btn').addEventListener('click', () => {
document.body.removeChild(dialog);
});
document.getElementById('save-settings-btn').addEventListener('click', () => {
saveSettings(dialog);
});
document.getElementById('reset-settings-btn').addEventListener('click', () => {
if (confirm('确定要重置所有设置到默认值吗?')) {
resetSettings(dialog);
}
});
}
// 保存设置
function saveSettings(dialog) {
const endpoint = document.getElementById('endpoint-input').value.trim();
const username = document.getElementById('username-input').value.trim();
const password = document.getElementById('password-input').value;
let directory = document.getElementById('directory-input').value.trim();
// 确保目录路径以 / 结尾(如果不为空)
if (directory && !directory.endsWith('/')) {
directory += '/';
}
if (!endpoint || !username || !password) {
showNotification('请填写完整的WebDAV配置', 'error');
return;
}
const newConfig = {
webdav: {
endpoint: endpoint,
id: username,
password: password,
directory: directory
}
};
saveConfig(newConfig);
showNotification('设置已保存', 'success');
document.body.removeChild(dialog);
}
// 重置设置
function resetSettings(dialog) {
document.getElementById('endpoint-input').value = defaultConfig.webdav.endpoint;
document.getElementById('username-input').value = defaultConfig.webdav.id;
document.getElementById('password-input').value = defaultConfig.webdav.password;
document.getElementById('directory-input').value = defaultConfig.webdav.directory;
showNotification('设置已重置为默认值', 'info');
}
// 测试WebDAV连接
function testWebDAVConnection() {
const endpoint = document.getElementById('endpoint-input').value.trim();
const username = document.getElementById('username-input').value.trim();
const password = document.getElementById('password-input').value;
if (!endpoint || !username || !password) {
showNotification('请先填写完整的WebDAV配置', 'error');
return;
}
showNotification('正在测试连接...', 'info');
GM_xmlhttpRequest({
method: 'PROPFIND',
url: endpoint,
headers: {
'Authorization': 'Basic ' + btoa(username + ':' + password),
'Depth': '0'
},
onload: function(response) {
if (response.status >= 200 && response.status < 300) {
showNotification('连接测试成功!', 'success');
} else {
showNotification(`连接失败: ${response.status} ${response.statusText}`, 'error');
}
},
onerror: function(error) {
showNotification('连接测试失败: ' + error.statusText, 'error');
}
});
}
// 设置按钮加载状态
function setButtonLoading(isLoading) {
const btn = document.getElementById('webdav-btn');
if (!btn) return;
if (isLoading) {
btn.innerHTML = '处理中...';
btn.style.background = '#6c757d';
btn.style.cursor = 'not-allowed';
btn.style.opacity = '0.7';
btn.disabled = true;
// 移除悬停效果
btn.onmouseenter = null;
btn.onmouseleave = null;
} else {
btn.innerHTML = 'WebDAV';
btn.style.background = '#007bff';
btn.style.cursor = 'pointer';
btn.style.opacity = '1';
btn.disabled = false;
// 重新添加悬停效果
btn.addEventListener('mouseenter', () => {
if (!btn.disabled) {
btn.style.background = '#0056b3';
btn.style.transform = 'translateY(-50%) scale(1.05)';
btn.style.boxShadow = '0 6px 16px rgba(0,123,255,0.4)';
}
});
btn.addEventListener('mouseleave', () => {
if (!btn.disabled) {
btn.style.background = '#007bff';
btn.style.transform = 'translateY(-50%) scale(1)';
btn.style.boxShadow = '0 4px 12px rgba(0,123,255,0.3)';
}
});
}
}
// 初始化
function init() {
createFloatingButton();
// 注册脚本菜单命令
GM_registerMenuCommand('WebDAV配置', showSettingsDialog);
}
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();