Gives a 0.1% chance to delete anything on any page, remembers deletions globally using multiple methods, and monitors dynamically loaded elements.
目前為
// ==UserScript==
// @name 0.1% Chance Global Element Deletion with Enhanced Persistence
// @namespace Fists
// @version 1.5
// @description Gives a 0.1% chance to delete anything on any page, remembers deletions globally using multiple methods, and monitors dynamically loaded elements.
// @author You
// @license CC BY 4.0; https://creativecommons.org/licenses/by/4.0/
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const STORAGE_KEY = 'globalDeletedNodes_v4';
// Load deleted nodes from localStorage
let deletedNodes = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
// Function to generate XPath for a node
function getXPathForElement(element) {
const idx = (sib, name) => sib
? idx(sib.previousElementSibling, name || sib.localName) + (sib.localName == name)
: 1;
const segs = elm => !elm || elm.nodeType !== 1
? ['']
: elm.id && document.getElementById(elm.id) === elm
? [`id("${elm.id}")`]
: [elm.localName.toLowerCase() + (elm.className ? `[@class="${elm.className}"]` : '') + `[${idx(elm)}]`, ...segs(elm.parentNode)];
return segs(element).join('/');
}
// Function to generate a selector for a node
function getSelectorForElement(element) {
if (element.id) {
return `#${element.id}`;
}
if (element.className) {
return `.${element.className.split(' ').join('.')}`;
}
return element.tagName.toLowerCase();
}
// Function to generate a robust identifier for a node
function getNodeIdentifier(element) {
const xpath = getXPathForElement(element);
const selector = getSelectorForElement(element);
const tagInfo = `${element.tagName}_${element.className}_${element.id}_${element.name}_${element.innerText.length}`;
return { xpath, selector, tagInfo };
}
// Function to check if a node has been previously deleted
function isNodeDeleted(identifiers) {
return deletedNodes.some(deleted =>
deleted.xpath === identifiers.xpath ||
deleted.selector === identifiers.selector ||
deleted.tagInfo === identifiers.tagInfo
);
}
// Function to store deleted node identifiers
function storeDeletedNode(identifiers) {
if (!isNodeDeleted(identifiers)) {
deletedNodes.push(identifiers);
localStorage.setItem(STORAGE_KEY, JSON.stringify(deletedNodes));
}
}
// Function to delete an element by various methods
function deleteElement(element, identifiers) {
if (element) {
element.remove();
storeDeletedNode(identifiers);
console.log('Element deleted and stored:', identifiers);
}
}
// Function to apply deletions using stored identifiers
function applyStoredDeletions() {
deletedNodes.forEach(identifiers => {
// Try XPath first
const xpathResult = document.evaluate(identifiers.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
let node = xpathResult.singleNodeValue;
// Try CSS Selector if XPath fails
if (!node) {
node = document.querySelector(identifiers.selector);
}
// Final fallback: Tag information search
if (!node) {
const allNodes = document.querySelectorAll('*');
node = [...allNodes].find(el => getNodeIdentifier(el).tagInfo === identifiers.tagInfo);
}
// Delete the node if found
if (node) {
deleteElement(node, identifiers);
}
});
}
// Function to attempt deletion of any node
function tryDeleteNode(node) {
const identifiers = getNodeIdentifier(node);
if (Math.random() < 0.001 && !isNodeDeleted(identifiers)) { // 0.1% chance
deleteElement(node, identifiers);
}
}
// Observer to watch for new elements, attributes, and nodes being added or modified in the DOM
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
tryDeleteNode(node);
}
});
});
});
// Configuration to observe child nodes and text content
observer.observe(document.documentElement, {
childList: true,
subtree: true,
characterData: true
});
// Initial pass to try deleting elements that are already loaded
const allNodes = document.querySelectorAll('*');
allNodes.forEach(element => {
tryDeleteNode(element);
});
// Apply deletions from stored identifiers
applyStoredDeletions();
})();