Veyra - Reaction Farm

Auto farm reactions with stamina/farm HUD and auto-login

// ==UserScript==
// @name         Veyra - Reaction Farm
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  Auto farm reactions with stamina/farm HUD and auto-login
// @match        https://demonicscans.org/title/*/chapter/*
// @match        https://demonicscans.org/signin.php
// @match        https://demonicscans.org/index.php
// @icon         https://www.google.com/s2/favicons?sz=64&domain=demonicscans.org
// @grant        none
// @license      GNU General Public License v3.0
// @run-at       document-end
// ==/UserScript==


(function() {
    'use strict';

    const AUTO_LOGIN_EMAIL = "YOUR_EMAIL_HERE"; // <-- Replace
    const AUTO_LOGIN_PASSWORD = "YOUR_PASSWORD_HERE"; // <-- Replace

    let isPaused = false;
    let scriptStopped = false;

    // --- HUD Setup ---
    const hud = document.createElement("div");
    hud.style.position = "fixed";
    hud.style.bottom = "10px";
    hud.style.right = "10px";
    hud.style.background = "rgba(0,0,0,0.8)";
    hud.style.color = "lime";
    hud.style.fontSize = "14px";
    hud.style.fontFamily = "monospace";
    hud.style.padding = "8px 12px";
    hud.style.borderRadius = "8px";
    hud.style.zIndex = "99999";
    hud.style.lineHeight = "1.5em";
    hud.innerHTML = `
        <div id="hud-status">⏳ Loading...</div>
        <button id="hud-toggle" style="
            margin-top:6px;
            padding:4px 8px;
            font-size:12px;
            border:none;
            border-radius:5px;
            cursor:pointer;
        ">⏸ Pause</button>
    `;
    document.body.appendChild(hud);

    const statusEl = document.getElementById("hud-status");
    const toggleBtn = document.getElementById("hud-toggle");

    toggleBtn.addEventListener("click", () => {
        isPaused = !isPaused;
        toggleBtn.textContent = isPaused ? "▶ Resume" : "⏸ Pause";
        hud.style.color = isPaused ? "yellow" : "lime";
    });

    // --- Utility functions ---
    function getStamina() {
        let staminaEl = document.evaluate(
            '//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[1]/span',
            document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
        ).singleNodeValue;
        if (!staminaEl) return null;
        let [current, max] = staminaEl.innerText.split('/').map(s => parseInt(s.replace(/,/g,'').trim(), 10));
        return { current, max };
    }

    function getFarm() {
        let farmEl = document.evaluate(
            '//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[2]/span',
            document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
        ).singleNodeValue;
        if (!farmEl) return null;
        let [current, max] = farmEl.innerText.split('/').map(s => parseInt(s.replace(/,/g,'').trim(), 10));
        return { current, max };
    }

    function updateHUD() {
        let staminaEl = document.evaluate(
            '//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[1]/span',
            document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
        ).singleNodeValue;

        let farmEl = document.evaluate(
            '//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[2]/span',
            document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
        ).singleNodeValue;

        let staminaText = staminaEl ? staminaEl.innerText.trim() : "0/0";
        let farmText = farmEl ? farmEl.innerText.trim() : "0/0";

        statusEl.innerText = `⚡ Stamina: ${staminaText}\n🌾 Farm: ${farmText}`;
    }

    function checkLimits() {
        let stamina = getStamina();
        let farm = getFarm();
        if (!stamina || !farm) return false;

        if (isPaused) return false;

        if (stamina.max - stamina.current <= 30) {
            hud.style.color = "orange";
            return false;
        }

        if (farm.current >= farm.max) {
            hud.style.color = "red";
            scriptStopped = true;
            return false;
        }

        hud.style.color = "lime";
        return true;
    }

    function clickReaction() {
        let reaction = document.evaluate(
            '/html/body/div[5]/center/div/div[1]/div[3]/div[1]',
            document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
        ).singleNodeValue;

        if (reaction) {
            reaction.scrollIntoView();
            reaction.click();
        }
    }

    function goNextPage() {
        let nextBtn = document.querySelector("body > div.chapter-info > div > a.nextchap");
        if (nextBtn) {
            window.location.href = nextBtn.href;
        } else {
            statusEl.innerText = "❌ Next button not found. Stopping script.";
            scriptStopped = true;
        }
    }

    function run() {
        updateHUD();

        if (!checkLimits()) {
            if (scriptStopped) return;
            setTimeout(run, 5000);
            return;
        }

        clickReaction();
        setTimeout(() => goNextPage(), 1500);
    }

    // --- Auto-login ---
    function autoLogin() {
        if (!window.location.href.includes("signin.php")) return false;
        const emailInput = document.evaluate('//*[@id="login-container"]/form/input[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        const passwordInput = document.evaluate('//*[@id="login-container"]/form/input[2]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        const loginBtn = document.evaluate('//*[@id="login-container"]/form/input[3]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        if (emailInput && passwordInput && loginBtn) {
            emailInput.value = AUTO_LOGIN_EMAIL;
            passwordInput.value = AUTO_LOGIN_PASSWORD;
            loginBtn.click();
            return true;
        }
        return false;
    }

    function startScript() {
        // --- Check if logged out on chapter page ---
        if (window.location.href.includes("/chapter/")) {
            const loginBtn = document.evaluate(
                '//*[@id="discuscontainer"]/div[1]/div[3]/div[5]/a[1]',
                document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
            ).singleNodeValue;

            if (loginBtn) {
                // Save current page to resume after login
                localStorage.setItem("veyra_resume_page", window.location.href);
                // Navigate to login page
                window.location.href = "https://demonicscans.org/signin.php";
                return;
            }
        }

        // --- If on login page ---
        if (window.location.href.includes("signin.php")) {
            if (autoLogin()) return;
            return; // wait for manual login if auto-login fails
        }

        // --- If came back from login, resume ---
        const resumePage = localStorage.getItem("veyra_resume_page");
        if (resumePage && resumePage !== window.location.href) {
            localStorage.removeItem("veyra_resume_page");
            window.location.href = resumePage;
            return;
        }

        // --- Start farming ---
        function waitForHUD() {
            const staminaEl = document.evaluate(
                '//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[1]/span',
                document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
            ).singleNodeValue;

            if (staminaEl) {
                setTimeout(run, 1000);
            } else {
                setTimeout(waitForHUD, 500);
            }
        }

        waitForHUD();
    }

    startScript();

})();