您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Detect curses on MZ forum posts. Works with Spanish words only.
- // ==UserScript==
- // @name Curse detector
- // @namespace mz-curse-detector
- // @description Detect curses on MZ forum posts. Works with Spanish words only.
- // @description:es Detectar groserías en los mensajes de los foros de MZ. Solamente detecta palabras en español.
- // @homepage https://github.com/rhonaldomaster/mz-curse-detector
- // @icon https://www.managerzone.com/favicon.ico?v2
- // @include https://*managerzone.*p=forum&sub=topic*
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_xmlhttpRequest
- // @version 0.4
- // @copyright GNU/GPL v3
- // @author rhonaldomaster
- // @license GPL-3.0-or-later
- // @compatible chrome
- // @compatible firefox
- // @compatible opera
- // @compatible safari
- // @compatible edge
- // ==/UserScript==
- // Default words in case the fetch fails
- const DEFAULT_CURSE_WORDS = [
- 'boba', 'bobo', 'boluda', 'bolu.da', 'boludo', 'bolu.do', 'bosta',
- 'bostera', 'bostero', 'burrazo', 'burro', 'cometrava', 'cometraba',
- 'concha', ' culo', 'estupida', 'estúpida', 'estupido', 'estúpido',
- 'forra', 'forro', 'gil', 'gilipolla', 'gonorrea', 'hdp', 'hipocrita',
- 'hipócrita', 'hijo de puta', 'hitler', 'idiota', 'imbecil', 'imbécil',
- 'kkk', 'kuka', 'lacra', 'la tenés adentro', 'la tenes adentro',
- 'la tenes bien adentro', 'la tenés bien adentro', 'la tenéis bien adentro',
- ' lta', 'malcogida', 'malcogido', 'mal cogida', 'mal cogido', 'malparida',
- 'malparido', 'mal parida', 'mal parido', 'marica', 'marmota', 'mediocre',
- 'mierda', 'miserable', 'mogolico', 'mogólico', 'montonero', 'mu ',
- 'muerde almohada', 'muerdealmohada', 'negro cabeza', 'patetico', 'patético',
- 'payasa', 'payaso', 'pelotuda', 'pelotudo', 'pene', 'perra', 'puta',
- 'putear', 'puto', 'retrasada', 'retrasado', 'ridicula', 'ridícula',
- 'ridiculo', 'ridículo', 'salame', 'sorete', 'sucio', 'subnormal',
- 'tarada', 'tarado', 'tonta', 'tontaza', 'tontazo', 'tonto', 'trampa',
- 'tramposa', 'tramposo', 'vende ajo', 'vendo ajo', 'verduler'
- ];
- // Cache configuration
- const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
- const CACHE_KEY = 'curseWordsCache';
- const CACHE_TIMESTAMP = 'curseWordsTimestamp';
- const CACHE_VERSION = '1.0.0';
- // GitHub Pages URL where the JSON is hosted
- const WORDS_JSON_URL = 'https://rhonaldomaster.github.io/mz-curse-detector/curse-words.json';
- // Store the current list of curse words
- let curseWords = [...DEFAULT_CURSE_WORDS];
- function searchAndHighlightWord(word, textContainer) {
- const warningColor = 'var(--curseColor)';
- const originalText = textContainer.innerHTML;
- if (originalText.indexOf(`<span style="color:${warningColor};font-weight:bold;text-decoration:underline;">`) > -1) {
- return;
- }
- const regex = new RegExp(`\\b${word}\\b`, 'gi');
- const highlightedText = originalText.replace(
- regex,
- `<span style="color:${warningColor};font-weight:bold;text-decoration:underline;">$&</span>`
- );
- if (highlightedText !== originalText) {
- textContainer.innerHTML = highlightedText;
- const editPostButton = textContainer.parentNode.querySelector('.fa-edit');
- if (editPostButton) {
- editPostButton.style.color = warningColor;
- }
- }
- }
- async function loadCurseWords() {
- // Try to get cached data first
- try {
- const cachedData = GM_getValue(CACHE_KEY);
- const cachedTime = GM_getValue(CACHE_TIMESTAMP);
- const cachedVersion = GM_getValue('curseWordsVersion');
- // If we have valid cached data and it's not expired
- if (cachedData && cachedTime && cachedVersion === CACHE_VERSION) {
- const age = Date.now() - parseInt(cachedTime, 10);
- if (age < CACHE_DURATION) {
- return JSON.parse(cachedData).words;
- }
- }
- // Fetch fresh data
- const response = await new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url: WORDS_JSON_URL,
- onload: resolve,
- onerror: reject,
- timeout: 5000 // 5 second timeout
- });
- });
- if (response.status >= 200 && response.status < 300) {
- const data = JSON.parse(response.responseText);
- // Cache the result
- GM_setValue(CACHE_KEY, JSON.stringify(data));
- GM_setValue(CACHE_TIMESTAMP, Date.now().toString());
- GM_setValue('curseWordsVersion', CACHE_VERSION);
- return data.words || DEFAULT_CURSE_WORDS;
- }
- } catch (error) {
- console.error('Failed to load curse words:', error);
- }
- // Fallback to default words
- return DEFAULT_CURSE_WORDS;
- }
- function detectCurses() {
- const messages = document.querySelectorAll('.forum-post-content');
- messages.forEach(message => {
- for (let i = 0; i < curseWords.length; i++) {
- searchAndHighlightWord(curseWords[i], message);
- }
- });
- }
- function addCSSVariables() {
- const root = document.querySelector(':root');
- root.style.setProperty('--curseColor', '#ff4800');
- }
- // Initialize the script
- async function init() {
- try {
- // Load curse words
- curseWords = await loadCurseWords();
- // Set up mutation observer
- const observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- if (mutation.type === 'childList') {
- mutation.addedNodes.forEach(node => {
- if (node.nodeType === 1 && node.classList.contains('forum-post-content')) {
- detectCurses();
- }
- });
- }
- });
- });
- // Find posts container and start observing
- const postsContainer = document.querySelector('.forum_content');
- if (postsContainer) {
- addCSSVariables();
- observer.observe(postsContainer, { childList: true, subtree: true });
- // Initial check
- detectCurses();
- // Add a small indicator
- addStatusIndicator();
- } else {
- console.error('Posts container not found.');
- }
- } catch (error) {
- console.error('Error initializing script:', error);
- }
- }
- // Add a small status indicator
- function addStatusIndicator() {
- const indicator = document.createElement('div');
- indicator.style.position = 'fixed';
- indicator.style.bottom = '10px';
- indicator.style.right = '10px';
- indicator.style.padding = '5px 10px';
- indicator.style.background = '#333';
- indicator.style.color = '#fff';
- indicator.style.borderRadius = '4px';
- indicator.style.fontSize = '12px';
- indicator.style.zIndex = '9999';
- indicator.textContent = `MZ Curse Detector v${GM_info.script.version} (${curseWords.length} palabras)`;
- document.body.appendChild(indicator);
- }
- // Start the script
- init();