0.1% Chance Total Deletion with Global Persistence

Gives a 0.1% chance to delete anything on any page, and remembers deletions across all pages.

当前为 2024-08-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 0.1% Chance Total Deletion with Global Persistence
  3. // @namespace Fists
  4. // @version 1.3
  5. // @description Gives a 0.1% chance to delete anything on any page, and remembers deletions across all pages.
  6. // @author You
  7. // @license CC BY 4.0; https://creativecommons.org/licenses/by/4.0/
  8. // @match *://*/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const STORAGE_KEY = 'globalDeletedNodes_v3';
  16.  
  17. // Load deleted nodes from localStorage
  18. let deletedNodes = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
  19.  
  20. // Function to generate a unique identifier for nodes
  21. function getNodeIdentifier(node) {
  22. if (node.nodeType === Node.ELEMENT_NODE) {
  23. return `${node.tagName}_${node.id}_${node.className}_${node.name}_${node.innerText.length}`;
  24. } else if (node.nodeType === Node.TEXT_NODE || node.nodeType === Node.COMMENT_NODE) {
  25. return `${node.nodeType}_${node.nodeValue.trim().slice(0, 50)}`;
  26. }
  27. return '';
  28. }
  29.  
  30. // Function to check if a node has been previously deleted
  31. function isNodeDeleted(node) {
  32. const identifier = getNodeIdentifier(node);
  33. return deletedNodes.includes(identifier);
  34. }
  35.  
  36. // Function to store deleted node identifiers
  37. function storeDeletedNode(node) {
  38. const identifier = getNodeIdentifier(node);
  39. if (!deletedNodes.includes(identifier)) {
  40. deletedNodes.push(identifier);
  41. localStorage.setItem(STORAGE_KEY, JSON.stringify(deletedNodes));
  42. }
  43. }
  44.  
  45. // Function to attempt deletion of any node
  46. function tryDeleteNode(node) {
  47. if (Math.random() < 0.001 && !isNodeDeleted(node)) { // 0.1% chance
  48. if (node.nodeType === Node.ELEMENT_NODE) {
  49. node.remove();
  50. console.log('Element deleted:', node);
  51. } else if (node.nodeType === Node.TEXT_NODE || node.nodeType === Node.COMMENT_NODE) {
  52. node.remove();
  53. console.log('Text or comment node deleted:', node);
  54. }
  55. storeDeletedNode(node);
  56. }
  57. }
  58.  
  59. // Observer to watch for new elements, attributes, and nodes being added or modified in the DOM
  60. const observer = new MutationObserver(mutations => {
  61. mutations.forEach(mutation => {
  62. // Try to delete the target node
  63. mutation.addedNodes.forEach(node => {
  64. if (!isNodeDeleted(node)) {
  65. tryDeleteNode(node);
  66. }
  67. });
  68. });
  69. });
  70.  
  71. // Configuration to observe child nodes and text content
  72. observer.observe(document.documentElement, {
  73. childList: true,
  74. subtree: true,
  75. characterData: true
  76. });
  77.  
  78. // Initial pass to try deleting elements, text nodes, and comments that are already loaded
  79. const allNodes = document.querySelectorAll('*');
  80. allNodes.forEach(element => {
  81. // Try to delete the element itself
  82. if (!isNodeDeleted(element)) {
  83. tryDeleteNode(element);
  84. }
  85. // Try to delete text nodes and comments within the element
  86. element.childNodes.forEach(child => {
  87. if (!isNodeDeleted(child)) {
  88. tryDeleteNode(child);
  89. }
  90. });
  91. });
  92. })();