Add a draggable blocklist management button on Douban.
当前为
// ==UserScript==
// @name Douban User Blocker
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Add a draggable blocklist management button on Douban.
// @author AAA_aaa
// @match *://*.douban.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const BLOCKLIST_KEY = 'doubanBlocklist';
function loadBlocklist() {
const stored = localStorage.getItem(BLOCKLIST_KEY);
return stored ? JSON.parse(stored) : [];
}
function saveBlocklist(blocklist) {
localStorage.setItem(BLOCKLIST_KEY, JSON.stringify(blocklist));
}
function addToBlocklist(userId) {
const blocklist = loadBlocklist();
if (!blocklist.includes(userId)) {
blocklist.push(userId);
saveBlocklist(blocklist);
//alert(`User ${userId} has been added to the blocklist.`);
} else {
alert(`User ${userId} is already in the blocklist.`);
}
removeBlockedElements();
updateBlocklistMenu();
}
function removeFromBlocklist(userId) {
let blocklist = loadBlocklist();
blocklist = blocklist.filter(id => id !== userId);
saveBlocklist(blocklist);
updateBlocklistMenu();
}
function removeBlockedElements() {
const blocklist = loadBlocklist();
document.querySelectorAll('.comment-item, .lite-comment-item, .review-item, .new-status, .ctsh').forEach(element => {
const link = element.querySelector('a[href^="https://www.douban.com/people/"]');
if (link) {
const userId = link.href.split('/')[4];
if (blocklist.includes(userId)) {
element.remove();
}
}
});
}
function addFloatingButton() {
const button = document.createElement('div');
button.id = 'drag-button';
button.textContent = 'Manage Blocklist';
document.body.appendChild(button);
let isDragging = false, offsetX, offsetY;
button.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - button.offsetLeft;
offsetY = e.clientY - button.offsetTop;
button.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
button.style.left = `${e.clientX - offsetX}px`;
button.style.top = `${e.clientY - offsetY}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
button.style.cursor = 'grab';
});
button.addEventListener('click', (e) => {
e.stopPropagation();
const menu = document.querySelector('.douban-menu');
menu.style.display = menu.style.display === 'block' ? 'none' : 'block';
});
}
function addBlocklistMenu() {
const menu = document.createElement('div');
menu.className = 'douban-menu';
menu.innerHTML = `
<div class="popup">
<h3>Blocked Users</h3>
<div class="blocklist-container">
<ul id="blocklist"></ul>
</div>
<input type="text" id="user-url" placeholder="Enter Douban user URL">
<button id="add-user">Add</button>
<button id="close-menu">Close</button>
</div>
`;
document.body.appendChild(menu);
document.getElementById('add-user').addEventListener('click', () => {
const userUrl = document.getElementById('user-url').value;
const match = userUrl.match(/https:\/\/www\.douban\.com\/people\/([^/]+)/);
if (match && match[1]) {
addToBlocklist(match[1]);
} else {
alert('Invalid Douban user URL.');
}
});
document.getElementById('close-menu').addEventListener('click', () => {
menu.style.display = 'none';
});
updateBlocklistMenu();
}
function updateBlocklistMenu() {
const blocklist = loadBlocklist();
const listElement = document.getElementById('blocklist');
listElement.innerHTML = '';
blocklist.forEach(userId => {
const li = document.createElement('li');
li.textContent = userId;
const removeBtn = document.createElement('button');
removeBtn.textContent = 'Remove';
removeBtn.className = 'del';
removeBtn.addEventListener('click', () => removeFromBlocklist(userId));
li.appendChild(removeBtn);
listElement.appendChild(li);
});
}
const style = document.createElement('style');
style.innerHTML = `
#drag-button {
position: fixed;
bottom: 20px;
right: 20px;
background: #28a745;
color: white;
padding: 10px 15px;
border-radius: 5px;
cursor: grab;
z-index: 1000;
}
.douban-menu {
width: 300px;
position: fixed;
top: 50px;
right: 20px;
background: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
display: none;
z-index: 999;
}
.blocklist-container {
max-height: 150px;
overflow-y: auto;
border: 1px solid #ccc;
padding: 5px;
}
.del {
cursor: pointer;
margin-left: 10px;
padding: 3px 8px;
border: none;
border-radius: 3px;
}
.del:hover {
background: darkred;
}
`;
document.head.appendChild(style);
function main() {
addFloatingButton();
addBlocklistMenu();
removeBlockedElements();
const observer = new MutationObserver(removeBlockedElements);
observer.observe(document.body, { childList: true, subtree: true });
}
main();
})();