☰

Semprot.com Bomber

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

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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 });
})();