AS mmd cleanup

This script is to clean up the spam in the Anime sharing MMD sharethread.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        AS mmd cleanup
// @version     1.3
// @namespace   mailto:[email protected]
// @author      perckle
// @description This script is to clean up the spam in the Anime sharing MMD sharethread.
// @license     MIT
// @match       https://www.anime-sharing.com/threads/mmd-discussion-and-sharing.1532636/*
// @grant       none
// @run-at      document-end
// ==/UserScript==

// Configuration flags
const CONFIG = {
    enableWordFilter: true,
    enableLinkCheck: true,
    enableHideBlockCheck: true,
    removeFormatting: false
};

// Function to check if text contains target words (case insensitive)
function containsTargetWords(text) {
    const normalizedText = text.toLowerCase();
    return normalizedText.includes('anyone') ||
           normalizedText.includes('any one') ||
           normalizedText.includes('anybody') ||
           normalizedText.includes('hero') ||
           normalizedText.includes('plz') ||
           normalizedText.includes('pls') ||
           normalizedText.includes('thx') ||
           normalizedText.includes('in advance');
}

// Function to check if element contains a direct child link
function containsLink(bbWrapper) {
    if (!bbWrapper || typeof bbWrapper.children === 'undefined') {
        console.log('Invalid element passed to containsLink');
        return false;
    }

    // Convert children to array and check only direct children
    const children = Array.from(bbWrapper.children);
    return children.some(child => {
        // Check if the child is an 'a' tag with href
        if (child.tagName === 'A' && child.hasAttribute('href')) {
            return true;
        }
        // Check if the child directly contains an 'a' tag (one level deep)
        return child.querySelector(':scope > a[href]') !== null;
    });
}

// Function to check if element contains hideBlock class
function containsHideBlock(bbWrapper) {
    if (!bbWrapper || typeof bbWrapper.querySelector !== 'function') {
        console.log('Invalid element passed to containsHideBlock');
        return false;
    }
    return bbWrapper.querySelector(':scope > .bbCodeBlock--hide, :scope > .hideBlock') !== null;
}

// Function to get text content excluding content within blockquotes
function getTextExcludingQuotes(element) {
    const clone = element.cloneNode(true);
    const blockquotes = clone.querySelectorAll('blockquote');
    blockquotes.forEach(quote => quote.remove());
    return clone.textContent.trim();
}

// Function to remove b and span tags while preserving their content
function removeFormattingTags(element) {
    if (!CONFIG.removeFormatting) return;

    const formattingTags = element.querySelectorAll('b, span');
    formattingTags.forEach(tag => {
        const textContent = document.createTextNode(tag.textContent);
        tag.parentNode.replaceChild(textContent, tag);
    });
}

// Main function to filter forum posts
function filterForumPosts() {
    const container = document.querySelector('.block--messages');
    if (!container) {
        console.log('Forum container not found, retrying...');
        return false;
    }

    const posts = container.querySelectorAll('.message-inner');
    if (posts.length === 0) {
        console.log('No posts found, retrying...');
        return false;
    }

    posts.forEach(post => {
        const bbWrapper = post.querySelector('.bbWrapper');
        if (!bbWrapper) return;

        let shouldRemove = true; // Start with true, set to false if any condition is met




        // Link check
        if (CONFIG.enableLinkCheck && shouldRemove) {
            if (containsLink(bbWrapper)) {
                shouldRemove = false;
            }
        }

        // HideBlock check
        if (CONFIG.enableHideBlockCheck && shouldRemove) {
            if (containsHideBlock(bbWrapper)) {
                shouldRemove = false;
            }
        }
              if (CONFIG.enableWordFilter) {
            const textContent = getTextExcludingQuotes(bbWrapper);
            if (containsTargetWords(textContent)) {
                shouldRemove = true;
            }
        }

        if (shouldRemove) {
            post.remove();
        } else if (CONFIG.removeFormatting) {
            removeFormattingTags(bbWrapper);
        }
    });

    return true;
}

// Function to wait for page to be fully rendered
function waitForPageLoad() {
    const observer = new MutationObserver((mutations, obs) => {
        const success = filterForumPosts();
        if (success) {
            obs.disconnect();
            console.log('Forum filtering complete');
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: false,
        characterData: false
    });

    document.addEventListener('DOMContentLoaded', () => {
        if (filterForumPosts()) {
            observer.disconnect();
            console.log('Forum filtering complete on initial load');
        }
    });

    setTimeout(() => {
        observer.disconnect();
        console.log('Stopped watching for page changes after timeout');
    }, 30000);
}

// Initialize the script
waitForPageLoad();