sNet / JVC Topic Blacklist 2.0

// ==/UserScript==
// ==UserScript==
// @name JVC Topic Blacklist 2.0
// @version 2.1
// @updateURL https://openuserjs.org/meta/sNet/JVC_Topic_Blacklist_2.0.meta.js
// @description Blacklist les topics à partir d'une liste de mots clés
// @author sNet
// @license MIT
// @match http://www.jeuxvideo.com/forums/0-51-0-1-0-*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @require https://code.jquery.com/ui/1.12.0/jquery-ui.min.js
// @grant GM_addStyle
// ==/UserScript==

// Code CSS

GM_addStyle (`

@import url(https://fonts.googleapis.com/css?family=Roboto:100);

.options-crumb {
align-items:center;
display:flex;
}

/* Button */

#btnParam {
font-family: 'Varela Round', sans-serif;
letter-spacing: 0.1em;
color: #e8e8e8;
border: none;
border-radius: 10px;
outline: none;
background: #3c3c3c;
background-size: 400% 400%;
cursor: pointer;
transition: all 0.3s ease;
filter:brightness(70%);
}

#btnParam:hover {
filter:brightness(100%);
}

.modal-closed {
display:none;
}

.modal-open {

font-family:"Roboto", sans-serif;
font-weight:bold;
display:grid;
grid-template-rows: 10% 85%;
grid-row-gap: 15px;
width:23%;
z-index:10000000000000000000000;
position:fixed;
top: 0px;
bottom:10px;
right: 0px;
background:#333;
border:solid #aaaaaa 0.5px;
}

.modal-open p {
color:#aaaaaa;
}

#modal-header {
align-items:center;
display:grid;
grid-template-columns: auto auto;
justify-items: center;
border-bottom:solid #aaaaaa 0.5px;
}

#modal-title {
color:#aaa;
letter-spacing: 0.1em;
font-family: 'Varela Round', sans-serif;
white-space: nowrap;
font-size:150%;
font-weight:normal;
}

#closebtnheader {
background:none;
border:none;
outline:none;
color:#aaaaaa;
font-size: 150%;
transition: all 0.3s ease;
}

#closebtnheader:hover {
color:#b00000
}

#modal-content {
display:grid;
grid-template-rows: 5% 80% 6% 9%;
grid-row-gap: 10px;
justify-items: center;
align-content: space-between;
}

#modal-content-btn {
display:grid;
grid-template-columns: auto auto;
grid-column-gap: 20px;
}

#btn-save {
background:teal;
border:none;
outline:none;
color:#aaaaaa;
filter:brightness(70%);
transition: all 0.3s ease;
font-size:15px;
padding:3.5px;
}

#btn-save:hover {
filter:brightness(100%);
}

#btn-save-reload {
background:#7070b6;
border:none;
outline:none;
color:#aaaaaa;
filter:brightness(70%);
transition: all 0.3s ease;
font-size:15px;
padding:3.5px;
}

#btn-save-reload:hover {
filter:brightness(100%);
}

#savedText {
font-weight:bold;
display:none;
align-self:center;
color:#66FF85;
border:solid #66FF85;
padding:3.5px;
}

/* TAG */

#blInput {
width: 90%;
border: #000 1px solid !important;
text-align:center;
}

#blInput:focus {
outline:none;
border: #6d6d6d 1px solid  !important;
}

#blValue {
width:90%;
background-color:#4a4a4a;
overflow:auto;
}

.blTag {
background-color:#1a1a1a;
padding:0.20em;
margin:5px;
display:inline-block;
}

.rmTag {
background:none;
border:none;
outline:none;
color:#aaaaaa;
font-size: 100%;
margin-left:10px;
transition: all 0.3s ease;
}

.rmTag:hover {color:#b00000;}


`);

// Code HTML

function injectHtml()
{
	$('body').append(`
<div id="blModal" class="modal-closed">
<div id="modal-header">
<div id="modal-title">
<modalTitle>Jvc Topic Blacklist</modalTitle>
</div>
<div id="modal-closer">
<button id="closebtnheader">╳</button>
</div>
</div>
<div id="modal-content">
<input id="blInput" placeholder="Saisir un mot à blacklister (insensible a la case)"/>
<div id="blValue">
</div>
<div id="modal-content-btn">
<button id="btn-save">Sauvegarder</button>
<button id="btn-save-reload">Sauvegarder et Rafraîchir</button>
</div>
<p id="savedText">Contenu sauvegardé</p>
</div>
</div>
`);
}


// Toutes les fonctions


// Recupération des valeurs dans le localstorage au chargement de la page

function initData(){
	var dataBl;
	var storedData = localStorage.getItem("dataBlJSON");
	if (storedData) {
		dataBl = JSON.parse(storedData);
		dataBl.sort();
	}
	else {
		console.log("error : no stored data");
		dataBl = {};
	}
	return dataBl;
}


// Le bouton permettant d'ouvrir le modal

function injectBtn() {
	$('.options-crumb').prepend('<button id="btnParam">Topic Blacklist</button>');
	$('#btnParam');
}


// Script du Modal

// Tout les trigger

function setTrig(openedOnce,dataBl) {
	$('#btnParam').click(function() {
		if($('#blModal').attr("class") == ('modal-closed')) {
			if(openedOnce==false) {
				initModal(dataBl);
				openedOnce=true;
			}
			else {
				openModal();
			}
		}
		else {
			closeModal();
		}
	});
	//
	$('#closebtnheader').click(function() {
		closeModal();
	});
	//
	$('#btn-save').click(function() {
		saveBl(dataBl);
	});
	//
	$('#btn-save-reload').click(function() {
		saveBl(dataBl);
		location.reload();
	});
	$('#blValue').on("click",".rmTag",function() {
		this.parentElement.remove();
	});
}

// Format Le string (Met le string en minuscule, Enleve les espaces inutiles, enleve les caracteres unicode)

function formatS(str) {
	var retStr = str.replace(/  /g,'').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, "")
	return retStr;
}

// Gestion des INPUT (pour ajouter des mots a blacklister)

function setInput(dataBl,regexL,regexR) {
	$('#blInput').on('keydown',function(e){
		if(e.keyCode == 13 && this.value){
			var formatedValue = formatS(this.value)
			console.log("formated : " + formatedValue);
			if(this.value == formatedValue || formatedValue.length>1) {
				var cantAdd=false;
				var tags = document.querySelectorAll('.blTag')
				for(var i=0;i<tags.length;i++) {
					let regex = new RegExp(regexL + tags[i].innerText.slice(0, -1) + regexR ,"gi");
					if(formatedValue.match(regex)) {
						var alreadyElement = tags[i];
						cantAdd=true;
						alreadyElement.scrollIntoView({behavior: 'smooth' });
						$('.blTag:eq('+ i +')').animate({backgroundColor:'#b000000'}, 1000).animate({backgroundColor:'#1a1a1a'}, 1000);
					}
				}
				if(cantAdd==false) {
					$('#blValue').append("<div class='blTag'>"+formatedValue+"<button class='rmTag'>╳</button></div>");
					tags[tags.length-1].scrollIntoView({behavior: 'smooth' });
					$('.blTag:eq('+ i +')').animate({backgroundColor:'#2c7064'}, 1000).animate({backgroundColor:'#1a1a1a'}, 1000);
				}
			}
			this.value = "";
		}
	});
}

// Quand le modal est ouvert pour la première fois on met tout les mots blacklisté

function initModal(dataBl) {
	$('.modal-closed').removeClass().addClass('modal-open');
	if(dataBl.length>0)
	{
		for(var i=0;i<dataBl.length;i++)
		{
			$('#blValue').append(`<div class="blTag">`+dataBl[i]+`<button class='rmTag'>╳</button></div>`);
		}
	}
}

// Une ouverture normal du modal ne fait qu'apparaître la fenêtre de modal

function openModal(){
	$('.modal-closed').removeClass().addClass('modal-open');
}


// La fermeture du modal cache la fenêtre

function closeModal() {
	$('.modal-open').removeClass().addClass('modal-closed');
}


// Sauvegarde des nouveaux mots ajoutés

function saveBl(dataBl) {
	dataBl=[];
	for(var i=0;i<$('.blTag').length;i++) {
		var value = $('.blTag')[i].innerText.slice(0, -1);
		dataBl[i]=value;
	}
	localStorage.setItem("dataBlJSON",  JSON.stringify(dataBl));
	$('#savedText').fadeIn()
	var fadeOutText = function () {
		$("#savedText").fadeOut(1000);
	};
	$("#savedText").fadeIn(1000);

    setTimeout(fadeOutText, 1000);
}

// La fonction de blacklist

function blacklister(dataBl,regexL,regexR){
	if(dataBl.length>1) {
		var listeTopic = $('.topic-list-admin li:has(.topic-title)');
		var nbDeleted=0;
		for(var i=0;i<listeTopic.length;i++){
			var topicEstSupprime = false;
			var titreTopic = formatS(listeTopic[i].children[0].children[1].title);
			for(var j=0;j<dataBl.length;j++) {
				let regex = new RegExp(regexL + dataBl[j] + regexR ,"gi");
				if(titreTopic.match(regex) && topicEstSupprime == false) {
					listeTopic[i].remove();
					console.log("Supprimé : " + titreTopic);
					topicEstSupprime = true;
					nbDeleted++;
				}
				else{
				}
			}
		}
		if(nbDeleted>0) {
			console.log("Nombre supprimé : " + nbDeleted);
			getTopic(nbDeleted,dataBl,regexL,regexR);
		}
	}
	else {
		console.log("error : array is empty");
	}
}

// On récupère un certains nombre de topic de la page suivante pour palier une suppresion de masse

function getTopic(nbDeleted,dataBl,regexL,regexR) {
    var start_time = new Date().getTime();
    var currLink = document.location.href;
    var regexLink = /https*:\/\/www\.jeuxvideo\.com\/forums\/0-51-0-1-0-([0-9]*)-0-blabla-18-25-ans\.htm/gi
    var linkMatch = regexLink.exec(currLink);
	var numPage = parseInt(linkMatch[1]) + 50;
	$.get("http://api.jeuxvideo.com/forums/0-51-0-1-0-" + numPage +"-0-blabla-18-25-ans.htm?r="+ new Date().getTime(), function(data) {
        var parser = new DOMParser();
        var doc = parser.parseFromString(data, "text/html");
        var listeTopic = doc.querySelectorAll('.liste-topics li');
        for (var i = 0; i < listeTopic.length; i++) {
			let inBlacklist=false;
			let titreTopicGet = formatS(listeTopic[i].children[0].children[1].children[0].innerText).replace(/^ /,"");
			for(var j=0;j<dataBl.length;j++) {
				let regex = new RegExp(regexL + dataBl[j] + regexR ,"gi");
				if(titreTopicGet.match(regex)) {
					inBlacklist = true;
					break;
				}
			}
			if(!inBlacklist) {
				//TOPIC
				let newTopic = document.createElement("li");
				newTopic.style.background = "#04352d"
				//SUJET
				let newSubject = document.createElement("span");
				newSubject.className = "topic-subject";
				//ICONE SUJET
				let newIcon = document.createElement("img");
				newIcon.className = "topic-img";
				newIcon.src = listeTopic[i].children[0].children[0].src;
				newSubject.append(newIcon);
				//TITRE SUJET
				let newTitle = document.createElement("a");
				newTitle.className = "lien-jv topic-title"
				newTitle.title = listeTopic[i].children[0].children[1].children[0].innerText.replace(/\n|  |\([0-9]*\)/g,"");
				newTitle.href = listeTopic[i].children[0].href;
				newTitle.innerText = listeTopic[i].children[0].children[1].children[0].innerText.replace(/\n|  |\([0-9]*\)/g,"");
				newSubject.append(newTitle);
				//AUTEUR
				let newAuteur = document.createElement("a");
				let nomNewAuteur = listeTopic[i].children[0].children[1].children[1].children[0].innerText.replace(/\n|  |\([0-9]*\)/g,"");
				newAuteur.className = "xXx text-user topic-author";
				newAuteur.target = "blank_"
				newAuteur.href = `http://www.jeuxvideo.com/profil/` + nomNewAuteur.toLowerCase() + `?mode=infos`
				newAuteur.innerText = nomNewAuteur
				//NOMBRE DE POST
				let newCount = document.createElement("span");
				newCount.className = "topic-count";
				newCount.innerText = listeTopic[i].children[0].children[1].children[0].children[0].innerText.replace(/\((.*)\)/,"$1");
				//DERNIER MSG
				let newDate = document.createElement("span");
				newDate.className = "topic-date";
				let newDateLink = document.createElement("a");
				newDateLink.className = "xXx lien-jv"
				newDateLink.href = listeTopic[i].children[0].href;
				newDateLink.innerText = listeTopic[i].children[0].children[1].children[1].children[1].innerText.replace(/\n|  |\([0-9]*\)/g,"")
				newDate.appendChild(newDateLink);
				//Ajout du topic
				newTopic.appendChild(newSubject);
				newTopic.appendChild(newAuteur);
				newTopic.appendChild(newCount);
				newTopic.appendChild(newDate);
				document.querySelector('.topic-list.topic-list-admin').appendChild(newTopic);
				nbDeleted--;
			}
			if(nbDeleted==0){
				break;
			}
		}
		if(nbDeleted>0) {
			console.log("ALERTE : Manque de topics");
		}
    });
}

// Fonction principal pour une meilleur organisation

function main() {
	var regexL = "(^|\\s|\\(|\\\"|\\[|\\;|\\,|\\:|\\/|\'|\-)(";
	var regexR = ")($|\\s|\\.|\\,|\\]|\\)|\\;|\\:|\\!|\\/|\\?|\'|\-)";
	var openedOnce=false;
	var dataBl=initData();
	injectBtn();
	injectHtml();
	setInput(dataBl,regexL,regexR);
	setTrig(openedOnce,dataBl);
	blacklister(dataBl,regexL,regexR);
}

// Execution du main quand la page est chargé ...

window.onload=main();