JVC Cloudflare Bypass

Bypass les captchas avec Cloudflare sur JVC

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         JVC Cloudflare Bypass
// @namespace    https://jeuxvideo.com/
// @version      1.11
// @description  Bypass les captchas avec Cloudflare sur JVC
// @author       HulkDu92
// @match        *://*.jeuxvideo.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @connect      cloudflare.com
// @connect      cloudflare.manfredi.io
// @run-at       document-end
// @license      MIT
// @icon         https://image.noelshack.com/fichiers/2025/06/5/1738891409-68747470733a2f2f74616d6e762e696d6769782e6e65742f63665f6279706173735f6c6f676f2e706e67.png
// ==/UserScript==

(function() {
    'use strict';

    const WARP_STATUS_KEY = "jvcWarpStatus";
    const CLOUDFLARE_TRACE_URL = "https://cloudflare.com/cdn-cgi/trace";
    const WARP_BUTTON_URL = "https://1.1.1.1/fr-FR/";
    const CLOUDFLARE_HUMAN_URL = "https://cloudflare.manfredi.io/test/";

    // Injecte les styles des deux boutons
    function injectStyles() {
      GM_addStyle(`
          .btn-warp {
              border: 0.0625rem solid var(--jv-text-secondary);
              background: var(--jv-text-secondary);
              color: #fff;
              font-weight: 500;
              padding: 0;
              font-size: 0.8125rem;
              height: 1.75rem;
              min-width: 6.375rem;
              line-height: 1.6875rem;
              cursor: pointer;
          }
          .btn-warp:hover {
              background: var(--jv-text-secondary-hover, var(--jv-text-secondary));
          }

          .btn-robot {
              border: 0.0625rem solid var(--jv-text-secondary);
              background: transparent;
              color: var(--jv-text-secondary);
              font-weight: 500;
              padding: 0;
              font-size: 0.8125rem;
              height: 1.75rem;
              min-width: 5.775rem;
              line-height: 1.6875rem;
              cursor: pointer;
              transition: all 0.2s ease;
              white-space: nowrap;
          }

          .btn-robot svg {
              width: 1.1rem;
              height: 1.1rem;
              stroke: white;
              padding-bottom: 2px;
          }

          .btn-robot:hover {
              border-color: var(--jv-text-secondary-hover, var(--jv-text-secondary));
              color:  var(--jv-text-secondary-hover, var(--jv-text-secondary));
          }
      `);
    }

    /**
     * Vérifie si Warp est activé et stocke le résultat dans sessionStorage.
     * Affiche le bouton si Warp est désactivé.
     */
    function checkWarpStatus() {
        const storedStatus = sessionStorage.getItem(WARP_STATUS_KEY);
        if (storedStatus !== null) {
            if (storedStatus === "false") showButtons();
            return;
        }

        GM_xmlhttpRequest({
            method: "GET",
            url: CLOUDFLARE_TRACE_URL,
            onload: response => {
                const warpActive = response.responseText.includes("warp=on");
                sessionStorage.setItem(WARP_STATUS_KEY, warpActive.toString());
                if (!warpActive) showButtons();
            }
        });
    }

    /**
     * Crée et affiche les deux boutons (Warp et Humanité).
     */
    function showButtons() {
        injectStyles();
        const warpButton = createWarpButton();
        const humanityButton = createHumanityButton();

        // Trouve les conteneurs pour chaque bouton, par exemple dans des zones différentes
        const targetElementWarp = document.querySelector('.header__globalUser'); // pour le bouton Warp
        const targetElementHumanity = document.querySelector('.bloc-pre-right'); // pour le bouton Humanity

        // Si l'élément cible pour Warp est trouvé, insère le bouton Warp dedans
        if (targetElementWarp) {
            targetElementWarp.insertBefore(warpButton, targetElementWarp.firstChild);
        } else {
            // Sinon, affiche le bouton en position fixe
            console.warn("Element cible pour Warp non trouvé, affichage en position fixed.");
            Object.assign(warpButton.style, {
                position: "fixed",
                bottom: "20px",
                right: "20px",
                zIndex: "9999"
            });
            document.body.appendChild(warpButton);
        }

        // Si l'élément cible pour Humanity est trouvé, insère le bouton Humanity dedans
        if (targetElementHumanity) {
            targetElementHumanity.insertBefore(humanityButton, targetElementHumanity.firstChild);
        } else {
            // Sinon, affiche le bouton en position fixe aussi pour Humanity
            console.warn("Element cible pour Humanity non trouvé, affichage en position fixed.");
            Object.assign(humanityButton.style, {
                position: "fixed",
                bottom: "20px",
                right: "100px", // Tu peux ajuster cette valeur pour le positionner à côté du premier bouton
                zIndex: "9999"
            });
            document.body.appendChild(humanityButton);
        }

    }

    /**
     * Crée le bouton pour activer Warp.
     * @returns {HTMLElement} Le bouton créé.
     */
    function createWarpButton() {
        const button = document.createElement("button");
        button.type = "button";
        button.className = "btn btn-warp";
        button.title = "Bloquer Captcha 🛇";
        button.textContent = "Bloquer Captcha";

        button.onclick = openCloudflareApp;
        return button;
    }

    /**
     * Ouvre un lien vers 1.1.1.1 pour son installation
     */
    function openCloudflareApp() {
        sessionStorage.removeItem(WARP_STATUS_KEY);
        alert(
            "Le blocage complet des Captchas est possible grâce à l'application officielle de Cloudflare: 1.1.1.1\n\n" +
            "Cette application agit comme un pass VIP pour Cloudflare et empêche tous les captchas sur JVC.\n\n" +
            "Il est recommandé de l'activer uniquement pour JVC.\n\n" +
            "C'est une solution radicale (en espérant qu'elle soit temporaire :hap:) pour éviter les captchas abusifs."
        );
        window.open(WARP_BUTTON_URL, "_blank");
    }

    /**
     * Crée le bouton pour vérifier l'humanité.
     * @returns {HTMLElement} Le bouton créé.
     */
    function createHumanityButton() {
        const button = document.createElement("button");
        button.type = "button";
        button.className = "btn btn-robot";
        button.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
                <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
                    <rect width="20" height="14" x="2" y="9" rx="4"/>
                    <circle cx="12" cy="3" r="2"/>
                    <path d="M12 5v4m-3 8v-2m6 0v2"/>
                </g>
            </svg>
             <span>Humain</span>
        `;

        button.onclick = fetchPercentage;
        return button;
    }

    /**
     * Récupère et affiche le pourcentage d'humanité.
     */
    function fetchPercentage() {
        GM_xmlhttpRequest({
            method: "GET",
            url: CLOUDFLARE_HUMAN_URL,
            onload: function(response) {
                const percentage = extractPercentage(response.responseText);
                if (percentage !== null) {
                    showPopup(percentage);
                } else {
                    alert("Erreur : Pourcentage non trouvé.");
                }
            },
            onerror: function() {
                alert("Erreur de récupération des données.");
            }
        });
    }

    function extractPercentage(htmlString) {
        let parser = new DOMParser();
        let doc = parser.parseFromString(htmlString, "text/html");

        let percentElement = Array.from(doc.querySelectorAll('*'))
            .find(el => el.textContent.includes('%') && el.textContent.includes('human'));

        if (!percentElement) return null;

        let match = percentElement.textContent.match(/(\d+)%/);
        return match ? parseInt(match[1], 10) : null;
    }

    function showPopup(percentage) {
        let popup = document.createElement('div');
        popup.id = 'human-check-popup';
        popup.innerHTML = `
            <div class="popup-content">
                <span class="popup-close">&times;</span>
                <p>Vous êtes ${percentage}% humain.</p>
                <div class="progress-bar-container">
                    <div class="progress-bar" style="width: ${percentage}%;"></div>
                </div>
            </div>
        `;
        document.body.appendChild(popup);

        popup.querySelector('.popup-close').addEventListener('click', function() {
            popup.remove();
        });

       GM_addStyle(`
          #human-check-popup {
              position: fixed;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              background: #181A1B;
              padding: 20px;
              box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
              border-radius: 10px;
              z-index: 10000;
              width: 300px;
              text-align: center;
              color: #F0EEEC;
          }

          .popup-content {
              position: relative;
          }

          .popup-close {
              position: absolute;
              top: 5px;
              right: 10px;
              font-size: 20px;
              cursor: pointer;
          }

          .progress-bar-container {
              width: 100%;
              height: 20px;
              background: #43413D;
              border-radius: 10px;
              margin-top: 10px;
              overflow: hidden;
          }

          .progress-bar {
              height: 100%;
              background: #006600;
              transition: width 0.5s;
          }
      `);

    }

    checkWarpStatus();
})();