1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | // ==UserScript==
// @name Desuarchive Word Filter
// @namespace -ACK!
// @version 1.0
// @description Word filter for Desuarchive posts, toggle with Shift+F or button
// @author NiggersTongueMyAnus
// @match https://desuarchive.org/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const style = document.createElement('style');
style.textContent = `
.filter-toggle-container {
position: fixed;
top: 10px;
right: 10px;
z-index: 10001;
font-family: Arial, sans-serif;
}
.filter-toggle-btn {
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
background: #6c757d;
color: #fff;
border: none;
transition: background 0.2s;
}
.filter-toggle-btn:hover {
background: #5a6268;
}
`;
document.head.appendChild(style);
// Create filter toggle button
const filterContainer = document.createElement('div');
filterContainer.className = 'filter-toggle-container';
const filterBtn = document.createElement('button');
filterBtn.className = 'filter-toggle-btn';
filterBtn.textContent = 'Filter: On';
filterContainer.appendChild(filterBtn);
document.body.appendChild(filterContainer);
// Word filter for posts and their replacement
const targetWords = ['Akemi', 'Ack', '!Akemi', 'ack', 'ACK'];
const replacementPhrases = ['I love you', 'Marry me', 'Steamy night!', 'Have SEX with me', '*kisses you*', 'I KNEEL'];
let filterEnabled = true;
const originalTexts = new Map(); // Store original text node values
function getRandomReplacement() {
return replacementPhrases[Math.floor(Math.random() * replacementPhrases.length)];
}
function filterTextNode(textNode) {
if (!textNode.nodeValue || !textNode.parentNode) return;
if (!filterEnabled) {
// Restore original text if filter is disabled
if (originalTexts.has(textNode)) {
textNode.nodeValue = originalTexts.get(textNode);
}
return;
}
// Store original text if not already stored
if (!originalTexts.has(textNode)) {
originalTexts.set(textNode, textNode.nodeValue);
}
let text = textNode.nodeValue;
let modified = false;
targetWords.forEach((word) => {
// Regex to match whole words/phrases
const regex = new RegExp(`\\b${word.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}\\b`, 'g');
if (regex.test(text)) {
text = text.replace(regex, getRandomReplacement());
modified = true;
}
});
if (modified) {
textNode.nodeValue = text;
//console.log('Filtered text node:', text);
}
}
function filterPostText(postTextElement) {
if (!postTextElement) return;
function processNode(node) {
// Skip greentext spans with backlinks
if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('greentext')) {
if (node.querySelector('a.backlink')) {
return; // Skip backlink greentext to prevent breaking format
}
}
if (node.nodeType === Node.TEXT_NODE) {
filterTextNode(node);
} else if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
node.childNodes.forEach(processNode);
}
}
processNode(postTextElement);
}
// Apply filter to existing posts
function applyFilterToPosts() {
const postWrappers = document.querySelectorAll('.post_wrapper');
postWrappers.forEach((wrapper) => {
const postText = wrapper.querySelector('.text');
if (postText) {
filterPostText(postText);
}
});
//console.log(`Applied filter to ${postWrappers.length} posts`);
}
// Toggle filter
function toggleFilter() {
filterEnabled = !filterEnabled;
filterBtn.textContent = `Filter: ${filterEnabled ? 'On' : 'Off'}`;
//console.log(`Filter toggled to: ${filterEnabled ? 'On' : 'Off'}`);
applyFilterToPosts();
}
// Shift+F to toggle filter
filterBtn.addEventListener('click', toggleFilter);
document.addEventListener('keydown', (e) => {
if (e.shiftKey && e.key.toLowerCase() === 'f') {
e.preventDefault();
toggleFilter();
}
});
// Initial filter application
applyFilterToPosts();
// Observe for new posts to filter
const postObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.matches('.post_wrapper')) {
const postText = node.querySelector('.text');
if (postText) {
filterPostText(postText);
}
} else {
const wrappers = node.querySelectorAll('.post_wrapper');
wrappers.forEach((wrapper) => {
const postText = wrapper.querySelector('.text');
if (postText) {
filterPostText(postText);
}
});
}
}
});
}
});
});
postObserver.observe(document.body, {
childList: true,
subtree: true
});
//console.log('Post MutationObserver set up for .post_wrapper');
})();
|