Mine Manager - Auto Proactive

Tự động chủ động gọi API không cần click giao diện

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

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

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name          Mine Manager - Auto Proactive
// @namespace     http://tampermonkey.net/
// @version       1.2.1
// @description   Tự động chủ động gọi API không cần click giao diện
// @author        Gemini
// @match        *://*/*
// @match         *://*.cnovel.com/*
// @grant         unsafeWindow
// @grant         GM_setValue
// @grant         GM_getValue
// @run-at        document-end
// ==/UserScript==
(function() {
    'use strict';
     const isGameDomain = () => {
        return /cmangax\d+\.com|cnovel|cmangapi/.test(location.hostname);
    };

    if (!isGameDomain()) return;

    // ==================== CẤU HÌNH ====================
    const CHECK_INTERVAL = 1 * 60 * 1000; // 5 phút check 1 lần
    const HARVEST_THRESHOLD = 60;        // Ngưỡng thu hoạch 60 phút

    console.log('%c[Auto Mine] Script đã nạp. Chế độ: CHỦ ĐỘNG (Proactive)', 'color: #00ff00; font-weight: bold;');

    // 1. Hàm lấy bảo mật từ window của game
    const getGameWindow = () => {
        return typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
    }
    const callGameFunc = (funcName, args = []) => {
        const targetWindow = getGameWindow();
        if (typeof targetWindow[funcName] === 'function') {
            try {
                return targetWindow[funcName](...args);
            } catch (e) {
                console.error(`Lỗi khi thực thi hàm ${funcName}:`, e);
                return null;
            }
        }
        return null;
    }
    function getSecurity() {
        if (typeof unsafeWindow.send_user_security === 'function') {
            return unsafeWindow.send_user_security();
        }
        return null;
    }

    let user_data = callGameFunc('get_user_security')
    let currentTarget = user_data.character

    // 2. HÀM QUAN TRỌNG: Tự gọi API score_list
    async function checkMineStatus() {
        console.log(`[Auto Mine] [${new Date().toLocaleTimeString()}] Đang tự động gửi request tới API...`);
        const url = `/api/score_list?type=battle_mine_target&target=${currentTarget}&_=${Date.now()}`;

        try {
            const response = await fetch(url, {
                method: 'GET',
                credentials: 'include',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                    'Accept': 'application/json'
                }
            });

            const data = await response.json();

            if (data && data.status === 1) {
                console.log('[Auto Mine] Đã nhận dữ liệu API thành công.');
                handleResponse(data);
            } else {
                console.warn('[Auto Mine] API trả về trạng thái lỗi (có thể do session hết hạn).');
            }
        } catch (error) {
            console.error('[Auto Mine] Lỗi khi chủ động thực hiện fetch:', error);
        }
    }

    function handleResponse(responseData) {
        if (!responseData.data || responseData.data.length === 0) {
            console.log('[Auto Mine] Không có dữ liệu ngồi mỏ. Đang chiếm lại mỏ cũ...');
            const savedId = GM_getValue('lastMineId');
            if (savedId) challengeMine(savedId);
            return;
        }

        const mineEntry = responseData.data[0];
        try {
            const mineData = JSON.parse(mineEntry.data);

            // Lấy "times" ở cấp ngoài của object miner như bạn yêu cầu
            const times = mineData.miner.times || 0;

            const mineId = mineEntry.id_score;

            console.log(`[Auto Mine] Target: ${currentTarget} | Score_od: ${mineId} |Đã ngồi: ${times}/${HARVEST_THRESHOLD} phút`);

            // Lưu dữ liệu để dùng lần sau (khi F5 trang)
            GM_setValue('lastMineId', mineId);
            GM_setValue('lastMineTarget', currentTarget);

            if (times >= HARVEST_THRESHOLD) {
                console.log('%c[Auto Mine] Đủ thời gian! Thực hiện thu hoạch ngay...', 'color: orange; font-weight: bold;');
                takeMineReward();
            }
        } catch (e) {
            console.error('[Auto Mine] Lỗi phân tích JSON từ API:', e);
        }
    }

    // 4. Hàm Thu hoạch
    async function takeMineReward() {
        const security = getSecurity();
        if (!security) return;

        const formData = new FormData();
        formData.append('action', 'battle_mine_take_reward');
        formData.append('target', 'public');

        if (typeof security === 'object') {
            for (const key in security) {
                formData.append(`user_security[${key}]`, security[key]);
            }
        }

        try {
            const res = await fetch('/assets/ajax/character_activity.php', {
                method: 'POST',
                body: formData,
                credentials: 'include'
            });
            const result = await res.json();
            console.log('[Auto Mine] Kết quả thu hoạch:', result);
        } catch (e) { console.error('[Auto Mine] Lỗi thu hoạch:', e); }
    }

    // 5. Hàm Chiếm mỏ
    async function challengeMine( mineId) {
        const security = getSecurity();
        if (!security) return;

        const formData = new FormData();
        formData.append('action', 'battle_mine_challenge');
        formData.append('target', 'public');
        formData.append('mine_id', mineId);

        if (typeof security === 'object') {
            for (const key in security) {
                formData.append(`user_security[${key}]`, security[key]);
            }
        }

        try {
            const res = await fetch('/assets/ajax/character_activity.php', {
                method: 'POST',
                body: formData,
                credentials: 'include'
            });
            const result = await res.json();
            console.log('[Auto Mine] Kết quả chiếm mỏ:', result);
        } catch (e) { console.error('[Auto Mine] Lỗi chiếm mỏ:', e); }
    }

    // ==================== KHỞI CHẠY ====================
    function start() {
        // Chạy lần đầu ngay lập tức khi load trang
        checkMineStatus();

        // Thiết lập lặp lại
        setInterval(checkMineStatus, CHECK_INTERVAL);

        console.log(`[Auto Mine] Hệ thống tự động đã bắt đầu. Chu kỳ: ${CHECK_INTERVAL/60000} phút.`);
    }

    // Đợi 3 giây sau khi trang load để đảm bảo các hàm của game đã sẵn sàng
    window.addEventListener('load', () => {
        setTimeout(start, 3000);
    });

})();