Full_Black_List

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

// ==UserScript==
// @name         Full_Black_List
// @namespace    Full_Black_List
// @version      0.21.5
// @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*
// @icon         https://images.emojiterra.com/microsoft/fluent-emoji/15.1/128px/1f6ab_color.png
// @license      MIT
// @grant        none
// ==/UserScript==


//1___FETCH___SYNCH__BL___(FETCH_FORUM_LIST_PAGE)___
async function synckBLForums() {
    let response = await fetch('/sso/blacklist.php');
    let htmlText = await response.text();
    let parser = new DOMParser();
    let doc = parser.parseFromString(htmlText, 'text/html');
    let pseudos = doc.querySelectorAll('#blacklist span');

    //synch_bl_local_storage<=>/sso/blacklist.php
    let pseudoList = [];
    pseudos.forEach(span => {
        pseudoList.push(span.textContent.trim());
    });
    localStorage.setItem('fullblacklistJVC', JSON.stringify(pseudoList));
}



//2___Fetch_MP_LIST_______(FETCH_MP_LIST_PAGE)___
let idListF = [];
let haListF = [];

async function fetchBlockedUsersListMPHash() {
    let response = await fetch('/messages-prives/indesirables.php');
    let htmlfofo = await response.text();
    let parser = new DOMParser();
    let doc = parser.parseFromString(htmlfofo, 'text/html');
    let listItems = doc.querySelectorAll('#blacklist .mp_delete_blacklist');
    //recupere pour chaque id
    listItems.forEach(user => {
        let idAlias = user.getAttribute('data-id');
        let hashtempo = user.getAttribute('data-hash');
        idListF.push(idAlias); // Get ID en list
        haListF.push(hashtempo);   // Get hash temp en list
    });
}

//___Clean_mp___
function deleteblacklistMP(idAlias) {
    const index = idListF.indexOf(idAlias);
    if (index === -1) return;

    const hash = haListF[index];
    const url = `/messages-prives/message.php?del_blacklist=${idAlias}&h=${hash}`;
    fetch(url);
}


//2b___Clean_mp_all_____
async function deleteblacklistMPALL() {
    let fetchPromises = idListF.map((idAlias, index) => {
        let hashtempo = haListF[index]; // Récupérer le hash associé à l'index
        let url = `/messages-prives/message.php?del_blacklist=${idAlias}&h=${hashtempo}`;
        return fetch(url);  // Effectuer la suppression
    });
    await Promise.all(fetchPromises); //toute les bl MP sont strike => continue
}


//3_______PAGE_DE______CONNEXION___(Login)___
if (window.location.href.indexOf('jeuxvideo.com/login') > -1) {
    localStorage.removeItem('fullblacklistJVC'); // efface local storage => en cas de deconnexion
}



//5______BLACKLIST____LISTE_SUJETS___(Liste_Sujet_et_Recherche)___
if (window.location.href.indexOf('jeuxvideo.com/forums/0-') > -1 || window.location.href.indexOf('jeuxvideo.com/recherche/forums/0-') > -1) {

    let liste = localStorage.getItem('fullblacklistJVC');
    // Si aucune blacklist locale, on synchronise depuis le serveur JVC et on recharge la page
    if (!liste) {
        synckBLForums()
            .then(() => location.reload());
    } else {
        // Liste des pseudos blacklistés en minuscules pour comparaison insensible à la casse
        let pseudos = JSON.parse(liste);
        let pseudosLower = pseudos.map(pseudo => pseudo.toLowerCase());
        // supprime ceux postés par un pseudo blacklisté
        document.querySelectorAll('li').forEach(item => {
            let auteur = item.querySelector('.topic-author');
            if (auteur && pseudosLower.includes(auteur.textContent.trim().toLowerCase())) {
                item.remove(); // Sujet supprimé du DOM
            }
        });
    }
}

//5B_______BOUTON_____BLACKLIST___LISTE_SUJET_(Liste_Sujet)_____
if (window.location.href.indexOf('jeuxvideo.com/forums/0-') > -1) {

    let divContainer = document.createElement('div');
    divContainer.className = 'custom-btn-container';
    
    divContainer.innerHTML = `
        <span id="bl-refresh" class="btn btn-actu-new-list-forum icon-refresh"
              title="Actualiser la blacklist des Sujets"
              style="border-radius:6px; min-width:5rem;">
            Actu BL
        </span>&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:4rem;">
                Voir BL
            </span>
        </a>
    `;

    // Ajouter la div juste après cette div spécifique
    let pagiBeforeListTopic = document.querySelector('.bloc-pagi-default .pagi-before-list-topic');
    pagiBeforeListTopic.parentNode.insertBefore(divContainer, pagiBeforeListTopic.nextSibling);


    document.getElementById('bl-refresh').addEventListener('click', synckBLForums);
    document.getElementById('bl-refresh').addEventListener('click', () => {
        alert('Filtrage des topics actualisés avec la blacklist JVC ✅');
        location.reload();
    });

}

//4______MASQUAGE_____BLOC____MESSAGE____FORUM__(Topic_1_42)____
if (window.location.href.indexOf('jeuxvideo.com/forums/1-') > -1 || window.location.href.indexOf('jeuxvideo.com/forums/42-') > -1 || window.location.href.indexOf('jeuxvideo.com/forums/message/') > -1) {

    //masquage_message
    let blacklistBlocks = document.querySelectorAll('.msg-pseudo-blacklist');
    blacklistBlocks.forEach(block => {
        block.remove();
    });

    //ajout dun event au bouton blacklist
    let blacklisterBtns = document.querySelectorAll('.picto-msg-tronche');
    blacklisterBtns.forEach(function(btn) {
        btn.addEventListener('click', function() {
            sessionStorage.setItem('fullblacklistJVCAwait', 'true');
        });
    });

    // Mise à jour de la Blacklist du script apres actualisation
    let bljvcawait = sessionStorage.getItem('fullblacklistJVCAwait');
    if (bljvcawait === 'true') {
        synckBLForums(); // fullblacklistJVCAwait est 'true' => force synch
        sessionStorage.removeItem('fullblacklistJVCAwait'); // Supprime la clé 'fullblacklistJVCAwait'
    }

}

//______________MASQUAGE____BLOC__MESSAGE_MP__(Message_MP)____
if (window.location.href.indexOf('jeuxvideo.com/messages-prives/message.php') > -1) {



    //ajout dun event au bouton blacklist
    let blacklisterBtns = document.querySelectorAll('.picto-msg-tronche');
    blacklisterBtns.forEach(function(btn) {
        btn.addEventListener('click', function() {
            let dataUrl = btn.getAttribute('data-url');
            sessionStorage.setItem('fullblacklistJVCIDMP', dataUrl);
            sessionStorage.setItem('fullblacklistJVCAwait', 'true');
        });
    });

    // Mise à jour de la Blacklist fofo du script apres actualisation
    let bljvcawait = sessionStorage.getItem('fullblacklistJVCAwait');
    if (bljvcawait === 'true') {
        (async () => {
            // Fetch recuperer hash preference forum
            let response = await fetch(forumHPage);
            let htmlfofo = await response.text();
            let parser = new DOMParser();
            let doc = parser.parseFromString(htmlfofo, 'text/html');
            let ajaxHashpref = doc.querySelector('#ajax_hash_preference_user');
            // preference_user_hash => necassaire pour ajouter à la blacklist JVC
            let fullidmp = sessionStorage.getItem('fullblacklistJVCIDMP');
            let match = fullidmp.match(/add_blacklist=(\d+)/); //id_pseudo
            let idAlias = match ? match[1] : null;
            let url = `/forums/ajax_forum_blacklist.php?id_alias_msg=${idAlias}&action=add&ajax_hash=${ajaxHashpref.value}`;
            let result = await fetch(url);
            await synckBLForums();
            sessionStorage.removeItem('fullblacklistJVCAwait'); // Supprime la clé 'fullblacklistJVCAwait'
            sessionStorage.removeItem('fullblacklistJVCIDMP'); // Supprime la clé
            let newUrl = location.href.replace(/&add_blacklist=[^&]+&h=[^&]+/, "");
            if (newUrl !== location.href) location.replace(newUrl);
        })();
    }



    //liste_local_storage_blacklist_les_MP_+_masquage
    function supprimerParListeDePseudos(pseudos) {
        let pseudosLower = pseudos.map(pseudo => pseudo.toLowerCase()); // Liste tous les pseudos en minuscules
        let blacklistBlocks = document.querySelectorAll('.bloc-message-forum');
        let clicked;
        blacklistBlocks.forEach(block => {
            let auteur = block.querySelector('.bloc-pseudo-msg'); // Cibler l'élément avec le pseudo
            let boutonBlacklist = block.querySelector('.picto-msg-tronche');
            if (auteur && pseudosLower.includes(auteur.textContent.trim().toLowerCase())) {
                boutonBlacklist.click(); // BL_MP
            }
        });
    }


    //masquage_message_BL_CLASSIQUE
    let blacklistBlocks = document.querySelectorAll('.msg-pseudo-blacklist');
    blacklistBlocks.forEach(block => {
        block.remove();
    });



    //recup_local_storage
    function getListeBlacklist() {
        let liste = localStorage.getItem('fullblacklistJVC');
        if (liste) {
            return JSON.parse(liste);
        } else {
            synckBLForums().then(() => location.reload());
        }
    }

    let pseudosBlacklist = getListeBlacklist();
    supprimerParListeDePseudos(pseudosBlacklist);

}


//________________Suuppression_combiné_BL___(Page_BlackList_MP)____
if (window.location.href.indexOf('jeuxvideo.com/messages-prives/indesirables.php') > -1) {
    document.querySelectorAll('.mp_delete_blacklist').forEach(function(button) {
        button.addEventListener('click', function() { 
            let userId = this.getAttribute('data-id'); // Récupère l'ID
            fetch(`/sso/ajax_delete_blacklist.php?id_alias_unblacklist=${userId}`); //Retire de la blacklist Fofo
            localStorage.removeItem('fullblacklistJVC'); //Retire du local storage
        });
    });
}

//________________MISE_A_JOUR_PAGE_BLACK_LISTE__(Page_BlackList_Forums)____
if (window.location.href.indexOf('jeuxvideo.com/sso/blacklist.php') > -1) {

    updatepseudosFofoBL(); //lit les pseudo visible sur la page

    // Suppression par pseudo
    let crosses = document.querySelectorAll('.icon-cross-entypo');
    crosses.forEach(cross => {
        cross.addEventListener('click', async () => {
            updatepseudosFofoBL(); // Mets à jour le localStorage des pseudos côté forum
            let listItem = cross.closest('li');  
            let idAlias = listItem.getAttribute('data-id-alias');  // Récupérer l'id depuis le parent
            //recupere la liste dans les MP une seule fois.
            if (typeof hasFetched === 'undefined') {
                await fetchBlockedUsersListMPHash();
                hasFetched = true;
            }
            deleteblacklistMP(idAlias); // Supprime le pseudo ciblé dans les MP
        });
    });


    function updatepseudosFofoBL() { //lit les pseudo visible sur la page
        setTimeout(() => {
            let pseudos = document.querySelectorAll('#blacklist span');
            let pseudoList = [];
            pseudos.forEach(span => {
                pseudoList.push(span.textContent.trim());
            });
            localStorage.setItem('fullblacklistJVC', JSON.stringify(pseudoList));
        }, 1000); //delais pour capturer la page à jour
    }
}

//_______________BOUTON_SCRIPT_PAGE__BLACKLIST___(Page_BlackList_Forums)____
if (window.location.href.indexOf('jeuxvideo.com/sso/blacklist.php') > -1) {
    'use strict';

    //SUPPRESSION TOTALE LOT FOFO + MP
    async function deleteBlacklist() {
        document.getElementById('bl-clear').textContent = 'Loading...';
        let listItems = document.querySelectorAll('#blacklist li');
        // Suppression All ID Fofo
        const fetchPromises = Array.from(listItems).map(li => {
            const idAlias = li.getAttribute('data-id-alias');
            return fetch(`/sso/ajax_delete_blacklist.php?id_alias_unblacklist=${idAlias}`);
        });
        await Promise.all(fetchPromises); //toute les bl fofo sont strike => continue

        // Suppression All ID MP
        await fetchBlockedUsersListMPHash(); // récupère sa propre liste depuis la messagerie
        await deleteblacklistMPALL(); // supprime côté MP

        window.location.reload();
    }

    // Fonction d'exportation de la Blacklist
    function exportBlacklist() {
        const idList = Array.from(document.querySelectorAll('#blacklist li'))
            .map(li => li.getAttribute('data-id-alias'));
    
        const blob = new Blob([JSON.stringify(idList, null, 2)], { type: 'application/json' });
        const link = Object.assign(document.createElement('a'), {
            href: URL.createObjectURL(blob),
            download: 'Blacklist_JVC.json'
        });
        link.click();
    }


    // Fonction d'importation de la Blacklist depuis un fichier JSON
    async function importBlacklist(event) {
        const file = event.target.files[0];
        if (!file) return;
        try {
            // Récupération du hash AJAX
            document.getElementById('bl-import').textContent = 'Load...';
            const html = await (await fetch(forumHPage)).text();
            const hash = new DOMParser()
                .parseFromString(html, 'text/html')
                .querySelector('#ajax_hash_preference_user')?.value;
            // Lecture + parsing du fichier JSON
            const blacklist = JSON.parse(await file.text());
            // Requêtes d’ajout parallèles
            await Promise.all(blacklist.map(id =>
                fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${id}&action=add&ajax_hash=${hash}`)
            ));
            window.location.reload();
        } catch (err) {
            alert("Erreur à l’import : " + err.message);
            window.location.reload();
        }
    }

    // CREATION BOUTON
    let container = document.querySelector('.layout__row.layout__content.layout__row--gutter.mb-5');
    if (!container) return;
    
    container.insertAdjacentHTML('beforeend', `
        <ul>
            <button id="bl-import" title="Importer BlackList depuis un Fichier" class="simpleButton" style="border-radius:6px;">
                Importer
            </button>&nbsp;
            <button id="bl-export" title="Exporter BlackList JVC en Fichier" class="simpleButton" style="border-radius:6px;">
                Exporter
            </button>
        </ul>
        <ul>
            <button id="bl-clear" title="Vider toute la blacklist JVC + MP + Script" class="simpleButton" style="border-radius:6px; background-color:red;">
                Vider BL Forum et MP
            </button>
        </ul>
    `);
    
    document.getElementById('bl-import').addEventListener('click', () => {
        let input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json';
        input.addEventListener('change', importBlacklist);
        input.click();
    });
    
    document.getElementById('bl-export').addEventListener('click', exportBlacklist);
    
    document.getElementById('bl-clear').addEventListener('click', () => {
        if (window.confirm('⚠️ Supprimer toute la blacklist (JVC + MP + Script) ??⚠️')) {
            deleteBlacklist();
        }
    });
}

forumHPage = '/forums/0-36-0-1-0-1-0-0.htm'


/*
MIT License

Copyright (c) 2025 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.
*/