☰

Semprot.com Bomber

Hides Semprot replies that lack images or links, keeping the main OP post safe.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Semprot.com Bomber
// @namespace    Violentmonkey Scripts
// @version      1.1.0
// @description  Hides Semprot replies that lack images or links, keeping the main OP post safe.
// @license      MIT
// @match        https://www.semprot.com/threads/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(async function() {
    'use strict';

    const cleanPath = window.location.pathname.replace(/\/page-\d+.*$/, '');
    const storageKey = 'xf_true_op_' + cleanPath;

    function getPostAuthor(post) {
        if (!post) return null;
        const dataAuthor = post.getAttribute('data-author');
        if (dataAuthor) return dataAuthor.trim();

        // Search for username elements, but explicitly ignore any inside quote blocks
        const usernames = post.querySelectorAll('.username, .message-name');
        for (let el of usernames) {
            if (!el.closest('.bbCodeBlock--quote')) {
                return el.textContent.trim();
            }
        }
        return null;
    }

    async function getOrFetchOpAuthor() {
        let opAuthor = sessionStorage.getItem(storageKey);
        if (opAuthor) return opAuthor;

        const posts = document.querySelectorAll('article.message--post');
        if (posts.length > 0 && !window.location.pathname.includes('/page-')) {
            opAuthor = getPostAuthor(posts[0]);
            if (opAuthor) {
                sessionStorage.setItem(storageKey, opAuthor);
                return opAuthor;
            }
        }

        try {
            const res = await fetch(cleanPath);
            const html = await res.text();
            const doc = new DOMParser().parseFromString(html, 'text/html');
            const firstPost = doc.querySelector('article.message--post');
            if (firstPost) {
                opAuthor = getPostAuthor(firstPost);
                if (opAuthor) {
                    sessionStorage.setItem(storageKey, opAuthor);
                    return opAuthor;
                }
            }
        } catch (err) {
            console.error('Could not fetch root OP:', err);
        }

        if (posts.length > 0) {
            opAuthor = getPostAuthor(posts[0]);
            if (opAuthor) sessionStorage.setItem(storageKey, opAuthor);
        }
        return opAuthor;
    }

    function hasMediaOrLink(post) {
        const messageBody = post.querySelector('.message-body, .bbWrapper');
        if (!messageBody) return false;

        // Check for real images/media, ignoring smilies
        const realImages = messageBody.querySelectorAll('img:not(.smilie), .bbImage, video, iframe, .bbMedia, picture');
        if (realImages.length > 0) return true;

        // Check for links, ignoring quotes and user mentions
        const links = messageBody.querySelectorAll('a');
        for (let a of links) {
            if (a.closest('.bbCodeBlock--quote')) continue;
            if (a.classList.contains('username') || a.hasAttribute('data-user-id')) continue;

            const href = a.getAttribute('href');
            if (href && !href.startsWith('#') && !href.startsWith('javascript:')) {
                return true;
            }
        }

        return false;
    }

    async function filterPosts() {
        const opAuthor = await getOrFetchOpAuthor();
        if (!opAuthor) return;

        const posts = document.querySelectorAll('article.message--post');
        const isPageOne = !window.location.pathname.includes('/page-') || window.location.pathname.endsWith('/page-1');

        posts.forEach((post, index) => {
            if (post.dataset.opProcessed) return;
            post.dataset.opProcessed = 'true';

            const postAuthor = getPostAuthor(post);

            // Nuke anyone who isn't the true OP
            if (postAuthor !== opAuthor) {
                post.style.display = 'none';
                return;
            }

            // Always keep page 1 opening post safe
            if (isPageOne && index === 0) {
                return;
            }

            // Nuke OP text-only replies that lack media or links
            if (!hasMediaOrLink(post)) {
                post.style.display = 'none';
            }
        });
    }

    await filterPosts();

    const observer = new MutationObserver(() => {
        filterPosts();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();