Full_Black_List

Supprime totalement les sujets des pseudo blacklistés depuis la blacklist JVC.

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

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Full_Black_List
// @namespace    Full_Black_List
// @version      0.61.0
// @description  Supprime totalement les sujets des pseudo blacklistés depuis la blacklist JVC.
// @author       Atlantis
// @match        *://www.jeuxvideo.com/recherche/forums/0-*
// @match        *://www.jeuxvideo.com/forums/0-*
// @match        *://www.jeuxvideo.com/forums/42-*
// @match        *://www.jeuxvideo.com/forums/1-*
// @match        *://www.jeuxvideo.com/forums/message*
// @match        *://www.jeuxvideo.com/messages-prives/message.php*
// @match        *://www.jeuxvideo.com/messages-prives/indesirables.php
// @match        *://www.jeuxvideo.com/sso/blacklist.php
// @match        *://www.jeuxvideo.com/login*
// @run-at       document-end
// @icon         https://images.emojiterra.com/microsoft/fluent-emoji/15.1/128px/1f6ab_color.png
// @license      MIT
// @grant        none
// ==/UserScript==


// FONCTIONS RESEAU FETCH :
//   GET : fonctionSynchBLForums() : blacklist.php => LocalStorage
//   GET : getBLListMP() : GET BlackList MP et Hash
//   POST : deleteBlacklistMP() : BlackListForum => Strike BlackListMP
//   POST : deleteBlacklistMPALL() : Strike ALL BlackListMP

// CODE PAR PAGE :
//           /login                            => Vide le Local torage
//   FOFO    /forums/0-* (liste sujets)        => Masque sujets via BlackList dans LOCAL STORAGE
//   FOFO    /forums/1- /42-                   => Masque messages BL + Synch BL Fofo => localStorage
//   MP      /messages-prives/message.php      => masque messages BL + Synch : BL localStorage <=> BL MP <=> BL Fofo
//   MP      /messages-prives/indesirables.php => Synck Suppresion MP vers Forum
//   COMPTE  /sso/blacklist.php                => Gestion BL Forum - MP + Boutons Import / Export / Reset


//CSS HIDE BlackList
const cssForum = document.createElement('style');
//CSS MP/PAGE HIDE
cssForum.textContent = `
/* Hide block*/
.msg-pseudo-blacklist {
    display: none;
}

/* Hide Quote*/
.bloc-message-forum .blockquote-jv--blacklist { background: rgba(155, 155, 155, .1) !important; }
.bloc-message-forum .blockquote-jv--blacklist > * {
    display:none;
}

/* Force Show block and Quotes*/
.conteneur-messages-pagi.show-blacklist .msg-pseudo-blacklist { display: block; }
.conteneur-messages-pagi.show-blacklist .bloc-message-forum .blockquote-jv--blacklist > * {
    display: block;
}`;

//CSS LIST SUJET FORCE SHOW
cssForum.textContent += `
/* Force Show Topic */
.conteneur-topic-pagi.show-blacklist .topic-list > li {
    display: grid;
}`;

//CSS LIST SUJET HIDDEN BY PSEUDO
function addBlacklistCSSList(user) {
    cssForum.textContent += `
    /* Hide Topic */
    li:has(> .topic-author[href*="/profil/${user}?"]) { 
        --topic-bl: 1;
        display: none;
        background-color: var(--jv-block-highlighted-bg-color) !important ;
    }`;
}

document.head.appendChild(cssForum);
//CSS FORUM END

///// FONTIONS FETCH GET HASH //////
async function fetchForHash(url = "/forums/0-36-0-1-0-1-0-guerre-des-consoles.htm") {
    const res = await fetch(url);
    const html = await res.text();
    const doc = new DOMParser().parseFromString(html, 'text/html');
    return doc.getElementById('ajax_hash_preference_user')?.value;

}

///// FONTIONS FETCH GET DOC //////
async function fetchParseDom(url) {
    const res = await fetch(url);
    const html = await res.text();
    return new DOMParser().parseFromString(html, 'text/html');
}

///// FONTIONS FETCH GET BLACKLIST TO LOCAL STORAGE //////
// /sso/blacklist.php
async function fonctionSynchBLForums() {
    let docFetched = await fetchParseDom('/sso/blacklist.php');
    let pseudos = docFetched.querySelectorAll('#blacklist span');

    // /SSO/BLACKLIST.PHP => VERS_LOCAL_STORAGE
    let pseudoList = [...pseudos].map(span => span.textContent.trim().toLowerCase());
    localStorage.setItem('fullBlacklistJVC', JSON.stringify(pseudoList));
}



///// FONTIONS FETCH GET BLACKLIST MP AND HASH //////
// /indesirables.php
async function getBLListMP() {
    const docFetched = await fetchParseDom('/messages-prives/indesirables.php');
    const listItems = docFetched.querySelectorAll('#blacklist .mp_delete_blacklist');

    const mpBlacklistHashIndex = {};
    listItems.forEach(user => {
        const idAlias = user.dataset.id;
        const hashTempo = user.dataset.hash;
        mpBlacklistHashIndex[idAlias] = hashTempo; // { [idAlias] : hashTempo }
    });
    return mpBlacklistHashIndex;
}

///// FONTIONS DEL PSEUDO MP //////
async function deleteBlacklistMP(idAlias, mpBlacklistHashIndex) {
    const hashTempo = mpBlacklistHashIndex[idAlias]; // { [idAlias] : hashTempo  }
    if (!hashTempo) return; //pas de hash indexe
    await fetch('/messages-prives/ajax/ajax_mp_blacklist_delete.php', {
        method: 'POST',
        body: new URLSearchParams({ id: idAlias, hash: hashTempo })
    });
}


///// FONTIONS DEL ALL PSEUDO MP //////
async function deleteBlacklistMPALL(mpBlacklistHashIndex, onProgress) {
    for (const idAlias in mpBlacklistHashIndex) {
        const hashTempo = mpBlacklistHashIndex[idAlias]; // { [idAlias] : hashTempo  }
        // Effectuer la fetch de suppression (EN MP)
        await fetch('/messages-prives/ajax/ajax_mp_blacklist_delete.php', {
            method: 'POST',
            body: new URLSearchParams({ id: idAlias, hash: hashTempo })
        });
        onProgress?.(); // Call Back avancement.
    }
}


///// SCRIPT PAR PAGE //////
//3_______PAGE_DE______CONNEXION___(Login)___
if (location.href.includes('jeuxvideo.com/login')) {
    localStorage.removeItem('fullBlacklistJVC'); // Efface LocalStorage => EN CAS DE DECONNEXION
}

//5_______LISTE_SUJET_____
if (location.href.includes('jeuxvideo.com/forums/0-')) {

    //HTML
    document.querySelector('.bloc-pagi-default .pagi-before-list-topic')?.insertAdjacentHTML('afterend', `
        <div>
            <button id="show-msg" class="btn btn-actu-new-list-forum"
                  title=""
                  style="border-radius:6px; min-width:4rem;">
                MSG BL
            </button>&nbsp;
            <button id="bl-refresh" class="btn btn-actu-new-list-forum icon-refresh"
                  title="Actualiser la blacklist des Sujets"
                  style="border-radius:6px; min-width: 3.5rem;">
                Actu
            </button>&nbsp;
            <a href="/sso/blacklist.php" style="outline:none;" target="_blank">
                <span class="btn btn-actu-new-list-forum"
                      title="Voir/Editer/Exporter la BlackList"
                      style="border-radius:6px; min-width:2rem;">
                    BL
                </span>
            </a>
        </div>
    `);
    //HTML-JS-IMPERATIF
    const showMsgBtn = document.querySelector('#show-msg');
    let countBlBtn;
    showMsgBtn.addEventListener('mouseenter', () => {
        countBlBtn = 0;
        const countBlock = document.querySelectorAll('.topic-list > li');
        for (const li of countBlock) {
            if (getComputedStyle(li).getPropertyValue('--topic-bl') === '1') countBlBtn++;
        }
        showMsgBtn.title = `${countBlBtn} topic(s) filtrés (Voir)`;
    });
    showMsgBtn.addEventListener('click', () => {
        document.querySelector('.conteneur-topic-pagi')?.classList.add('show-blacklist');
        showMsgBtn.textContent = `(${countBlBtn}) BL`;
    });
    document.querySelector('#bl-refresh').addEventListener('click', async () => {
        await fonctionSynchBLForums();
        alert('Filtrage des topics actualisés avec la blacklist JVC ✅');
        location.reload();
    });

}

//5B______LISTE_SUJET ET_RECHERCHE_________
if (location.href.includes('jeuxvideo.com/forums/0-') || location.href.includes('jeuxvideo.com/recherche/forums/0-')) {

    let listeLocalStorage = localStorage.getItem('fullBlacklistJVC');
    if (!listeLocalStorage) {
        fonctionSynchBLForums().then(() => location.reload());
        return;
    }

    const blacklistStorage = JSON.parse(listeLocalStorage);
    //AJOUTER PSEUDO EN CSS
    for (const user of blacklistStorage) {
        addBlacklistCSSList(user);
    }

    //Doublage Div pour eviter bug alternance couleur
    const countBlock = document.querySelectorAll('.topic-list > li');
    [...countBlock].filter(li => getComputedStyle(li).display === 'none').forEach(block =>
        block.insertAdjacentHTML("afterend", `<li class="topic-ghost-block" style="display:none;"></li>`)
    );
}

//6_______TOPIC_MASQUAGE_________
if (location.href.includes('jeuxvideo.com/forums/1-') || location.href.includes('jeuxvideo.com/forums/42-') || location.href.includes('jeuxvideo.com/forums/message/')) {

    //HTML
    document.querySelector('.bloc-pre-left .group-one > a')?.insertAdjacentHTML('afterend', `
        <button id="show-msg" class="btn btn-actu-new-list-forum"
             title=""
             style="min-width:5rem;">
            MSG BL
        </button>
    `);

    //HTML-JS-IMPERATIF
    const showMsgBtn = document.querySelector('#show-msg');
    let countBlBtn = 0;
    showMsgBtn?.addEventListener('mouseenter', () => {
        countBlBtn = document.querySelectorAll('.msg-pseudo-blacklist, .msg-pseudo-blacklist-off').length;
        showMsgBtn.title = `${countBlBtn} message(s) filtrés (Voir)`;
    });
    showMsgBtn?.addEventListener('click', () => {
        document.querySelector('.conteneur-messages-pagi')?.classList.add('show-blacklist');
        showMsgBtn.textContent = `(${countBlBtn}) BL`;
    });

    //JS Conteneur
    const scopeForumBlocs = document.querySelector('.conteneur-messages-pagi');
    scopeForumBlocs.addEventListener('click', async(e) => {
        const btnPicto = e.target.closest('.picto-msg-tronche');
        const btnCancel = e.target.closest('.btn-blacklist-cancel');
        if (e.target.closest('#jvchat-main')) return; //dont touche if jvchat
        if (btnPicto) {
            sessionStorage.setItem('fullBlacklistJVCAwait', 'true');

            e.preventDefault(); e.stopImmediatePropagation();
            const hash = document.getElementById('ajax_hash_preference_user').value;
            const btnPictoId = btnPicto.dataset.idAlias;
            await fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${btnPictoId}&action=add&ajax_hash=${hash}`);
            location.reload();

        } else if (btnCancel) {
            sessionStorage.setItem('fullBlacklistJVCAwait', 'true');
        }
    }, { capture: true });


    //Doublage Div pour eviter bug alternance couleur
    document.querySelectorAll('.msg-pseudo-blacklist').forEach(block =>
        block.insertAdjacentHTML("afterend", `<div class="bloc-message-block" style="display:none;"></div>`)
    );

    //Class_for_Hides_Quotes
    function hidePseudoQuotes() {
        const blacklistStorage = JSON.parse(localStorage.getItem("fullBlacklistJVC") || "[]");
        document.querySelectorAll(".blockquote-jv > p:first-of-type").forEach(p => {
            const txtQuotClean = p.textContent.replace(/\s+/g, ' ');
            const pseudoIRC = txtQuotClean.match(/<([^>]+)>/)?.[1]?.toLowerCase(); //IRC
            const pseudoForum = txtQuotClean.match(/(\S+)\s+a écrit :/)?.[1]?.toLowerCase(); //FOFO
            if (blacklistStorage.includes(pseudoForum) || blacklistStorage.includes(pseudoIRC)) {
                p.closest(".blockquote-jv").classList.add("blockquote-jv--blacklist");
            }
        });
    }
    hidePseudoQuotes();

    // Mise à jour de la Blacklist du script APRES actualisation
    if (sessionStorage.getItem('fullBlacklistJVCAwait') === 'true') {
        fonctionSynchBLForums().then(hidePseudoQuotes);
        sessionStorage.removeItem('fullBlacklistJVCAwait');
    }

}

//7_____PARTIE__MP__________________
if (location.href.includes('jeuxvideo.com/messages-prives/message.php')) {

    //JS Conteneur
    // [1] Ajout d'un event sur les boutons "blacklist MP" pour quils agissent aussi sur la blacklist forum
    const scopeMPBlocs = document.querySelector('.conteneur-messages-pagi');
    scopeMPBlocs.addEventListener('click', (e) => {
        const btnPicto = e.target.closest('.picto-msg-tronche');
        if (e.target.closest('#jvchat-main')) return; //dont touche if jvchat
        if (btnPicto) {
            const idAlias = btnPicto.dataset.url.match(/add_blacklist=(\d+)/)[1];
            sessionStorage.setItem('fullBlacklistJVCidAlias', idAlias);
        }
    }, { capture: true });

    // [2] localStorage => simulation de clic sur bouton "blacklist MP"
    let listeLocalStorage = localStorage.getItem('fullBlacklistJVC');
    if (!listeLocalStorage) {
        fonctionSynchBLForums().then(() => location.reload());
        return;
    }

    // Liste pseudos en minuscules
    const blacklistStorage = JSON.parse(listeLocalStorage);
    const blacklistSet = new Set(blacklistStorage);
    document.querySelectorAll('.bloc-pseudo-msg').forEach(pseudoblock => {
         const pseudo = pseudoblock.textContent.trim().toLowerCase();
         if (blacklistSet.has(pseudo)) pseudoblock.closest('.bloc-message-forum').querySelector('.picto-msg-tronche')?.click();
    });

    // [3] Appel black list MP => Synch Fofo
    let idAlias = sessionStorage.getItem('fullBlacklistJVCidAlias');
    if (idAlias) {
      (async () => {
        // Fetch recuperer hash preference forum
        let hashValue = await fetchForHash();

        // AjoutBL_Forum
        await fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${idAlias}&action=add&ajax_hash=${hashValue}`);
        await fonctionSynchBLForums();
        //Clean
        sessionStorage.removeItem('fullBlacklistJVCidAlias'); // Supprime ID => Il vient d'etre traité.
      })();
    }

    // [4] Cacher les messages déjà blacklistés
    document.querySelectorAll('.msg-pseudo-blacklist').forEach(block =>
        block.insertAdjacentHTML("afterend", `<div class="bloc-message-block" style="display:none;"></div>`)
    );

}

//8_____PAGE_BLACKLIST_MP__________________
if (location.href.includes('jeuxvideo.com/messages-prives/indesirables.php')) {

    // Une suppression dans la BlackList MP => Suppression BL Forum + Suppression LocalStorage
    document.querySelectorAll('.mp_delete_blacklist').forEach(button => {
        button.addEventListener('click', () => {
            const userId = button.dataset.id;
            fetch(`/sso/ajax_delete_blacklist.php?id_alias_unblacklist=${userId}`);
            localStorage.removeItem('fullBlacklistJVC');
        });
    });
}

//9_____PAGE_BLACKLIST_Forums_SYNCH_________________
if (location.href.includes('jeuxvideo.com/sso/blacklist.php')) {

    fonctionSynchBLForumsNoFetch(); // Liste Page vers LocalStorage

    let mpBlacklistHashIndex;
    // Suppression par pseudo
    document.querySelectorAll('.icon-cross-entypo').forEach(cross => {
        cross.addEventListener('click', async () => {
           const idAlias = cross.closest('li')?.dataset.idAlias;
           if (!mpBlacklistHashIndex) {
               mpBlacklistHashIndex = await getBLListMP();
           }
           await deleteBlacklistMP(idAlias, mpBlacklistHashIndex);
           fonctionSynchBLForumsNoFetch();
        });
    });


    async function fonctionSynchBLForumsNoFetch() { //lit les pseudo visible sur la page
        await new Promise(resolve => setTimeout(resolve, 1000)); //delais pour capturer la page à jour

        let pseudos = document.querySelectorAll('#blacklist span');
        let pseudoList = [...pseudos].map(span => span.textContent.trim().toLowerCase());
        localStorage.setItem('fullBlacklistJVC', JSON.stringify(pseudoList));
    }
}

//9b_____PAGE_BLACKLIST_Forums_GESTION_IMPORT_EXPORT_________________
if (location.href.includes('jeuxvideo.com/sso/blacklist.php')) {

    // FUNC SUPPRESSION TOTALE BL LOT FOFO + MP
    async function deleteAllBlacklist() {
        document.querySelector('#bl-clear').textContent = 'Loading...';
        let listItems = document.querySelectorAll('#blacklist li');

        // Nettoyage de TOUT pseudo blacklistes
        let count = 1;
        for (const liItem of listItems) {
            const idAlias = liItem.dataset.idAlias;
            await fetch(`/sso/ajax_delete_blacklist.php?id_alias_unblacklist=${idAlias}`);
            document.querySelector('#bl-clear').textContent = `Loading (${count})`;
            count++;
        }

        // Nettoyage de TOUT pseudo blacklistes en MP
        let countMP = 1
        const mpBlacklistHashIndex = await getBLListMP();
        await deleteBlacklistMPALL(mpBlacklistHashIndex, () => { // supprime côté MP
            document.querySelector('#bl-clear').textContent = `Loading (OK) (MP : ${countMP})`;
            countMP++;
        });
        window.location.reload();
    }


    // FUNC IMPORTATION BLACKLIST fichier JSON
    async function importBlacklist(e) {
        const fileJson = e.target.files[0];
        if (!fileJson) return;

        // Lecture + parsing du fichier JSON
        let blacklistjson;
        try {
            blacklistjson = JSON.parse(await fileJson.text());
        } catch {
            return alert("Fichier JSON invalide.");
        }

        document.querySelector('#bl-import').textContent = 'Load...';

        // REQUÊTES D’AJOUT UN À UNE FOFO
        let hashValue = await fetchForHash();
        let count = 1;
        for (const obj of blacklistjson) {
            await fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${obj.id}&action=add&ajax_hash=${hashValue}`);
            document.querySelector('#bl-import').textContent = `Load (${count})`;
            count++;
        }
        window.location.reload();
    }

    // FUNC EXPORT BLACKLIST fichier JSON
    function exportBlacklist() {
        const blacklistItems = [...document.querySelectorAll('#blacklist li')];
        const idList = blacklistItems.map(li => ({
            id: li.dataset.idAlias,
            pseudo: li?.textContent.trim()
        }));

        const blob = new Blob([JSON.stringify(idList, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = 'Blacklist_JVC.json';
        link.click();
        URL.revokeObjectURL(url); // LIBERE LA MEMOIRE apres telechargement
    }

    // CREATION_HTML_BOUTON
    let container = document.querySelector('#page-compte .layout__content');
    container.insertAdjacentHTML('beforeend', `
        <ul>
            <button id="bl-import" title="Importer BlackList depuis un Fichier" class="btn btn-secondary" style="border-radius:6px;">
                Importer
            </button>&nbsp;
            <button id="bl-export" title="Exporter BlackList JVC en Fichier" class="btn btn-secondary" style="border-radius:6px;">
                Exporter
            </button>
        </ul>
        <ul>
            <button id="bl-clear" title="Vider toute la blacklist JVC + MP + Script" class="btn btn-danger" style="border-radius:6px;">
                Vider BL Forum et MP
            </button>
        </ul>
    `);

    // ATTACH_LISTENER_IMPORT
    container.querySelector('#bl-import').addEventListener('click', () => {
        let input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json';
        input.addEventListener('change', importBlacklist);
        input.click();
    });

    // ATTACH_LISTENER_EXPORT
    container.querySelector('#bl-export').addEventListener('click', exportBlacklist);

    // ATTACH_LISTENER_SUPPRESSION
    container.querySelector('#bl-clear').addEventListener('click', () => {
        if (!window.confirm('⚠️ Supprimer toute la blacklist (JVC + MP + Script) ? ⚠️')) return;
        deleteAllBlacklist();
    });
}


/*
MIT License

Copyright (c) 2026 Atlantis (https://github.com/Lantea-Git)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/