// ==UserScript==
// @name Full_Black_List
// @namespace Full_Black_List
// @version 0.32.1
// @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==
// === SOMMAIRE RAPIDE DU SCRIPT ===
// FONCTIONS RESEAU FETCH :
// [1] synckBLForums : synchro BL forums vers localStorage
// [2] fetchBlockedUsersListMPHash / deleteblacklistMP : gestion BL MP via hash
//
// PAGES GEEES :
// [3] /login → Réinitialise la BL locale
// [5] /forums/0-* (liste sujets) → Masque sujets BL + boutons Actu/Accès
// [6] /forums/1- /42- /message/* → Masque messages BL + synchro après ajout
// [7] /messages-prives/message.php → Ajoute à la BL forum + masque messages
// [8] /messages-prives/indesirables.php → Suppression ciblée BL MP
// [9] /sso/blacklist.php → Gestion BL Forum + boutons import/export/reset
//
///// FONTIONS RESEAU FETCH //////
const forumPageUrlForm = '/forums/0-36-0-1-0-1-0-0.htm'
//1___FETCH___SYNCH__BL___(FETCH_FORUM_LIST_PAGE)_
//PUSH — met à jour le localStorage à partir du serveur
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');
// /SSO/BLACKLIST.PHP => SYNCH_BL_LOCAL_STORAGE
let pseudoList = [...pseudos].map(span => span.textContent.trim());
localStorage.setItem('fullblacklistJVC', JSON.stringify(pseudoList));
}
//2___Fetch_MP_LIST_______(FETCH_MP_LIST_PAGE)___
// GET — récupère les ID et hash des utilisateurs blacklistés dans la messagerie
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
});
}
//2A___CLEAN_MP___
// POST — supprime un utilisateur blacklisté de la messagerie privée
function deleteblacklistMP(idAlias) {
const index = idListF.indexOf(idAlias);
if (index === -1) return;
const hashtempo = haListF[index];
const url = `/messages-prives/message.php?del_blacklist=${idAlias}&h=${hashtempo}`;
fetch(url);
}
//2B___CLEAN_MP_ALL_____
// POST_LOT — supprime tous les utilisateurs blacklistés de la messagerie (boucle async)
async function deleteblacklistMPALL() {
/* requettes simulatanées => a eviter
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
*/
for (const [index, idAlias] of idListF.entries()) {
const hashtempo = haListF[index]; // Récupérer le hash associé à l'index
const url = `/messages-prives/message.php?del_blacklist=${idAlias}&h=${hashtempo}`;
await fetch(url); // Effectuer la suppression
}
}
///// PAGES GEREES //////
//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
const blacklistStorage = JSON.parse(liste).map(pseudo => pseudo.toLowerCase());
// supprime ceux postés par un pseudo blacklisté
document.querySelectorAll('.topic-list > li').forEach(sujetList => {
let auteur = sujetList.querySelector('.topic-author')?.textContent.trim().toLowerCase();
if (auteur && blacklistStorage.includes(auteur)) {
sujetList.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> 
<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();
});
}
//6______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
document.querySelectorAll('.msg-pseudo-blacklist').forEach(block => block.remove());
//ajout dun event au bouton blacklist
let blacklisterBtns = document.querySelectorAll('.picto-msg-tronche');
blacklisterBtns.forEach(btn => {
btn.addEventListener('click', () => {
sessionStorage.setItem('fullblacklistJVCAwait', 'true');
});
});
// Mise à jour de la Blacklist du script apres actualisation
if (sessionStorage.getItem('fullblacklistJVCAwait') === 'true') {
synckBLForums();
sessionStorage.removeItem('fullblacklistJVCAwait');
}
}
//7______________MASQUAGE____BLOC__MESSAGE_MP__(Message_MP)____
if (window.location.href.indexOf('jeuxvideo.com/messages-prives/message.php') > -1) {
// [1] Préparer les boutons "blacklist" pour synch vers fofo
let blacklisterBtns = document.querySelectorAll('.picto-msg-tronche');
blacklisterBtns.forEach(btn => {
btn.addEventListener('click', () => {
const idAlias = btn.getAttribute('data-url').match(/add_blacklist=(\d+)/)[1];
sessionStorage.setItem('fullblacklistJVCidAlias', idAlias);
});
});
// [2] localStorage => simulation de clic sur bouton (blacklist MP)
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 {
const blacklistStorage = JSON.parse(liste).map(pseudo => pseudo.toLowerCase()); // Liste tous les pseudos en minuscules
const messageBlocks = document.querySelectorAll('.bloc-message-forum')
messageBlocks.forEach(block => {
const pseudoBloc = block.querySelector('.bloc-pseudo-msg')?.textContent.trim().toLowerCase();
const blacklistButton = block.querySelector('.picto-msg-tronche');
if (pseudoBloc && blacklistStorage.includes(pseudoBloc) && blacklistButton) {
// Simule un clic pour déclencher la blacklist côté MP (native) + forum (script)
blacklistButton.click();
}
});
}
// [3] Si un pseudo a été blacklisté => ajouter aussi côté forum
let idAlias = sessionStorage.getItem('fullblacklistJVCidAlias');
if (idAlias) {
(async () => {
// Fetch recuperer hash preference forum
let html = await (await fetch(forumPageUrlForm)).text();
let parser = new DOMParser();
let doc = parser.parseFromString(html, 'text/html');
let hashValue = doc.querySelector('#ajax_hash_preference_user')?.value;
// AjoutBL_Forum
await fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${idAlias}&action=add&ajax_hash=${hashValue}`);
await synckBLForums();
//clean
sessionStorage.removeItem('fullblacklistJVCidAlias'); // Supprime ID attente
})();
}
// [4] Cacher les messages déjà blacklistés
document.querySelectorAll('.msg-pseudo-blacklist').forEach(block => block.remove());
}
//8________________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
});
});
}
//9________________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 le hash associé au pseudo dans les MP (UNE SEULE FOIS).
let hasFetched;
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].map(span => span.textContent.trim());
localStorage.setItem('fullblacklistJVC', JSON.stringify(pseudoList));
}, 1000); //delais pour capturer la page à jour
}
}
//9b_______________BOUTON_SCRIPT_PAGE__BLACKLIST___(Page_BlackList_Forums)____
if (window.location.href.indexOf('jeuxvideo.com/sso/blacklist.php') > -1) {
'use strict';
//SUPPRESSION TOTALE BL LOT FOFO + MP
async function deleteBlacklist() {
document.getElementById('bl-clear').textContent = 'Loading...';
let listItems = document.querySelectorAll('#blacklist li');
// Suppression All ID Fofo
/* requettes simulatanées => a eviter
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 Fofo une à une
let count = 1;
for (const li of listItems) {
const idAlias = li.getAttribute('data-id-alias');
await fetch(`/sso/ajax_delete_blacklist.php?id_alias_unblacklist=${idAlias}`);
document.getElementById('bl-clear').textContent = `Loading (${count})`;
count++;
} //toute les bl fofo sont strike => continue
// Suppression All ID MP
document.getElementById('bl-clear').textContent = `Loading...`;
await fetchBlockedUsersListMPHash(); // récupère sa propre liste depuis la messagerie
await deleteblacklistMPALL(); // supprime côté MP
window.location.reload();
}
//EXPORT BLACKLIST fichier JSON
function exportBlacklist() {
const blacklistItems = [...document.querySelectorAll('#blacklist li')];
const idList = blacklistItems.map(li => ({
id: li.getAttribute('data-id-alias'),
pseudo: li.querySelector('span')?.textContent.trim()
}));
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();
}
//IMPORTATION BLACKLIST
//EXPORT BLACKLIST fichier JSON
async function importBlacklist(bljson) {
const filejson = bljson.target.files[0];
if (!filejson) return;
try {
// Lecture + parsing du fichier JSON
const blacklistjson = JSON.parse(await filejson.text());
// Récupération du hash AJAX
document.getElementById('bl-import').textContent = 'Load...';
const html = await (await fetch(forumPageUrlForm)).text();
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
let hash = doc.querySelector('#ajax_hash_preference_user')?.value;
/* Requêtes simulatanées => a eviter
await Promise.all(blacklistjson.map(obj =>
fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${obj.id}&action=add&ajax_hash=${hash}`)
));
*/
// REQUÊTES D’AJOUT UN À UNE
let count = 1;
for (const obj of blacklistjson) {
await fetch(`/forums/ajax_forum_blacklist.php?id_alias_msg=${obj.id}&action=add&ajax_hash=${hash}`);
document.getElementById('bl-import').textContent = `Load (${count})`;
count++;
}
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>
<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();
}
});
}
/*
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.
*/