Respawn Lot Message Delete

Suppression msg lot

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Respawn Lot Message Delete
// @version      5.9.6
// @description  Suppression msg lot
// @namespace    Respawn Lot Message Delete
// @author       Craftbukkit debug par ROMANCE_DAWN adapt for payload
// @icon         https://images.emojiterra.com/microsoft/fluent-emoji/15.1/128px/1f5d1_color.png
// @match        https://www.jeuxvideo.com/profil/*?mode=historique_forum*
// @license MIT
// ==/UserScript==

//Global Variables
let nMessageAlreadyDelete;
let nMessageNonDelete;
let nMessageDelete;
let freshHash;

//Show Update UI
function hydrateUI(nPage) {
    document.getElementById("papage").innerHTML = `
            <b>Vidage Message :</b><br>
            Message supprimé : ${nMessageDelete} <br>
            Message déjà supprimé : ${nMessageAlreadyDelete} <br>
            Message non supprimé : ${nMessageNonDelete} <br>
            Page n°${nPage}<br><br>`;
}

const sleep = ms => new Promise(r => setTimeout(r, ms));


// GET PARSE Payload64 From Raw
function getJson64PayloadRaw(rawData) {
    const payload64 = rawData.match(/jvc\.\w+Payload\s*=\s*["']([^"']+)["']/)?.[1];
    return payload64 ? JSON.parse(atob(payload64)) : null;
}

//Fetch 403 / 429 - JSON / HTML
async function fetchGetPage403(url) {
    const jsonHeaders = { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' };
    for (let attempt = 1; attempt <= 6; attempt++) {
        await sleep(500);
        const response = await fetch(url, { headers : jsonHeaders });
        if (response.status === 403 || response.status === 429) {
            console.log(`Rate limit ${response.status}, attente 3s (essai ${attempt}/6)`);
            await sleep(3000);
            continue;
        }
        return response;
    }
    return null;
}

// Get_Hash_By_Fetch
async function fechGetHash() {
    const response = await fetch('https://www.jeuxvideo.com/forums/0-36-0-1-0-1-0-guerre-des-consoles.htm');
    const data = await response.text();
    const jsonData = getJson64PayloadRaw(data);
    return jsonData?.ajaxModerationToken;
}

//REQUEST DELETE MESSAGE
async function requestDeleteMessage(idMessages, retryOnce = true) {
    const reponse = await fetch(`https://www.jeuxvideo.com/forums/message/delete?ids=${idMessages.join(',')}&type=delete&ajax_hash=${freshHash}`, { method: 'POST' });
    if (!reponse.ok && retryOnce) {
        freshHash = await fechGetHash();
        return requestDeleteMessage(idMessages, false);
    }
    return reponse;
}


const monthsJvc = { janvier: 0, février: 1, mars: 2, avril: 3, mai: 4, juin: 5, juillet: 6, août: 7, septembre: 8, octobre: 9, novembre: 10, décembre: 11 };

async function videPage(nPage, data) {
    //Lecture champs User
    const [yearMin, monthMin, dayMin] = document.getElementById('mindate').value.split('-');
    const [yearMax, monthMax, dayMax] = document.getElementById('maxdate').value.split('-');
    let minDate = new Date(yearMin, monthMin - 1, dayMin).getTime(); //TimeStamp Min
    let maxDate = new Date(yearMax, monthMax - 1, dayMax).getTime(); //TimeStamp Max


    let jsonData;
    try {
        jsonData = JSON.parse(data); //Json from serv
    } catch {
        jsonData = getJson64PayloadRaw(data); //FallBack Html Payload
    }

    const messages = jsonData?.listMessage ?? [];

    const messageToDelete = [];
    for (const message of messages) {
        if (message.stateMessage === 'msg-visible') {
            const idMessage = message.id;



            // publishedDate format: "19 sptembre 1999 à 00:00:00"
            const [day, monthStr, year] = message.publishedDate.split(' ');
            if (!(monthStr in monthsJvc)) throw new Error('Mois invalide => Annulation'); //Guard

            const messageTimestamp = new Date(year, monthsJvc[monthStr], day).getTime();



            // DATES MATCH => DELETE
            if (messageTimestamp >= minDate && messageTimestamp <= maxDate) {
                /*
                const deletedMessage = await requestDeleteMessage([idMessage]);
                if (!deletedMessage?.ok) {
                    throw new Error(`Échec suppression message ${idMessage}`);
                }
                nMessageDelete++;
                */
                messageToDelete.push(idMessage);
            } else {
                nMessageNonDelete++;
            }
        } else {
            nMessageAlreadyDelete++;
        }
    }

    // SUPPRESSION EN UNE SEULE REQUETTE POUR EVITER DE SPAM
    if (messageToDelete.length) {
        const deletedMessage = await requestDeleteMessage(messageToDelete);
        if (!deletedMessage?.ok) {
            throw new Error(`Échec suppression de (${messageToDelete.length} messages)`);
        }
        nMessageDelete += messageToDelete.length;
    }
    hydrateUI(nPage);

    const nextPage = jsonData?.pagerView?.next?.url;
    if (nextPage) {
        console.log(nextPage);
        const response = await fetchGetPage403(nextPage);
        const nextData = await response.text();
        await videPage(nPage + 1, nextData);
    } else {
        alert('Dernière Page Traité')
    }
}

document.querySelector(".titre-bloc").insertAdjacentHTML('beforeend', `
    <div style="font-size: 1.2rem;"><br>  -> Du : 
    <input type="date" id="mindate" value="1970-01-01" class="form-control" style="width: 230px; font-weight: 600; font-size: 1rem; display: inline-flex; margin: 5px;">
     au 
    <input type="date" id="maxdate" value="1998-01-01" class="form-control" style="width: 230px; font-weight: 600; font-size: 1rem; display: inline-flex; margin: 5px;">
    <button class="btn icon-bin" title="Tout supprimer" id="viderAll" style="display: inline-flex; align-items: center; font-size: 1.1rem; height: 2.2rem;">Vider</button></div>`);

document.getElementById("viderAll").onclick = async function() {
    if (confirm("Le script va commencer de la page en cours\n/!\ Êtes-vous sûr de vouloir tout supprimer ? /!\\ ")) {

        this.style.display = 'none';
        document.getElementById('forum-main-col').style.display = 'none';
        document.getElementById('mindate').disabled = true;
        document.getElementById('maxdate').disabled = true;

        nMessageDelete = 0;
        nMessageAlreadyDelete = 0;
        nMessageNonDelete = 0;
        const nPage = 1;

        document.querySelector(".titre-head-bloc").insertAdjacentHTML("afterend", "<span id='papage' style='display: block;'></span>");
        hydrateUI(nPage);

        //Get hash from forum (Le hash de suppression nest plus dans lhisto on va le chercher sur les forums).
        freshHash = await fechGetHash();

        const startUrl = location.href;

        const response = await fetchGetPage403(startUrl);
        const startData = await response.text();
        await videPage(nPage, startData);
    }
};