Auto Code Activator Gaijin // Автоматическая активация кодов на сайте Gaijin

Автоматическая активация кодов на сайте Gaijin с функциями сохранения и удаления кодов

// ==UserScript==
// @name         Auto Code Activator Gaijin // Автоматическая активация кодов на сайте Gaijin
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Автоматическая активация кодов на сайте Gaijin с функциями сохранения и удаления кодов
// @author       z1zod, BALCETUL
// @match        https://store.gaijin.net/activate.php
// @grant        none
// @license      MIT
// ==/UserScript==


(function () {
    'use strict';

    const waitTime = 2000; // Время ожидания после клика
    const refreshInterval = 3000; // Интервал перезагрузки страницы
    const clickInterval = 1000; // Интервал для имитации кликов

    // Функция для ожидания
    function waitFor(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // Функция для создания панели статуса
    function createStatusPanels() {
        const statusPanel = document.createElement('div');
        statusPanel.id = 'status-panel';
        statusPanel.style.position = 'fixed';
        statusPanel.style.top = '10px';
        statusPanel.style.right = '10px';
        statusPanel.style.width = '300px';
        statusPanel.style.padding = '10px';
        statusPanel.style.backgroundColor = '#333';
        statusPanel.style.color = '#fff';
        statusPanel.style.zIndex = '10000';
        statusPanel.style.borderRadius = '8px';
        statusPanel.style.display = 'flex';
        statusPanel.style.flexDirection = 'column';
        statusPanel.style.gap = '10px';

        // Информационное сообщение над полем ввода кодов
        const infoMessage = document.createElement('div');
        infoMessage.id = 'info-message';
        infoMessage.style.backgroundColor = '#444';
        infoMessage.style.border = '1px solid #666';
        infoMessage.style.borderRadius = '4px';
        infoMessage.style.padding = '10px';
        infoMessage.style.fontSize = '12px';
        infoMessage.style.marginBottom = '10px';
        infoMessage.style.color = '#ccc';
        statusPanel.appendChild(infoMessage);

        const codesInputLabel = document.createElement('label');
        codesInputLabel.textContent = 'Введите коды:';
        statusPanel.appendChild(codesInputLabel);

        const codesInput = document.createElement('textarea');
        codesInput.id = 'codes-input';
        codesInput.style.width = '100%';
        codesInput.style.height = '80px';
        codesInput.style.marginBottom = '10px';
        codesInput.style.backgroundColor = '#555';
        codesInput.style.color = '#fff';
        codesInput.style.border = '1px solid #777';
        codesInput.style.fontSize = '12px';
        statusPanel.appendChild(codesInput);

        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.flexDirection = 'column';
        buttonContainer.style.gap = '10px';

        const toggleButton = document.createElement('button');
        toggleButton.textContent = 'Начать активацию';
        toggleButton.style.backgroundColor = '#4CAF50';
        toggleButton.style.color = '#fff';
        toggleButton.style.border = 'none';
        toggleButton.style.padding = '10px 20px';
        toggleButton.style.cursor = 'pointer';
        toggleButton.style.borderRadius = '4px';
        toggleButton.style.transition = 'background-color 0.3s';
        toggleButton.addEventListener('mouseover', () => {
            toggleButton.style.backgroundColor = '#45a049';
        });
        toggleButton.addEventListener('mouseout', () => {
            toggleButton.style.backgroundColor = '#4CAF50';
        });
        buttonContainer.appendChild(toggleButton);

        const saveButton = document.createElement('button');
        saveButton.textContent = 'Сохранить коды';
        saveButton.style.backgroundColor = '#4CAF50';
        saveButton.style.color = '#fff';
        saveButton.style.border = 'none';
        saveButton.style.padding = '10px 20px';
        saveButton.style.cursor = 'pointer';
        saveButton.style.borderRadius = '4px';
        saveButton.style.transition = 'background-color 0.3s';
        saveButton.addEventListener('mouseover', () => {
            saveButton.style.backgroundColor = '#45a049';
        });
        saveButton.addEventListener('mouseout', () => {
            saveButton.style.backgroundColor = '#4CAF50';
        });
        buttonContainer.appendChild(saveButton);

        const deleteButton = document.createElement('button');
        deleteButton.textContent = 'Удалить коды';
        deleteButton.style.backgroundColor = '#f44336';
        deleteButton.style.color = '#fff';
        deleteButton.style.border = 'none';
        deleteButton.style.padding = '10px 20px';
        deleteButton.style.cursor = 'pointer';
        deleteButton.style.borderRadius = '4px';
        deleteButton.style.transition = 'background-color 0.3s';
        deleteButton.addEventListener('mouseover', () => {
            deleteButton.style.backgroundColor = '#e53935';
        });
        deleteButton.addEventListener('mouseout', () => {
            deleteButton.style.backgroundColor = '#f44336';
        });
        deleteButton.style.fontSize = '12px';
        deleteButton.style.marginTop = '10px';
        buttonContainer.appendChild(deleteButton);

        statusPanel.appendChild(buttonContainer);

        const statusText = document.createElement('div');
        statusText.style.marginTop = '10px';
        statusText.id = 'status-text';
        statusPanel.appendChild(statusText);

        const failedText = document.createElement('div');
        failedText.style.marginTop = '10px';
        failedText.style.color = '#ef5d5d';
        failedText.style.fontSize = '12px';
        failedText.id = 'failed-text';
        statusPanel.appendChild(failedText);

        document.body.appendChild(statusPanel);

        return { statusText, codesInput, saveButton, deleteButton, toggleButton, failedText, infoMessage };
    }

    // Функция для обновления панели статуса
    function updateStatusPanel(activeCount, totalCodes, failedCodes, messageType) {
        const statusText = document.getElementById('status-text');
        const failedText = document.getElementById('failed-text');
        const infoMessage = document.getElementById('info-message');

        if (statusText) {
            statusText.innerHTML = `
                <p>Всего кодов: ${totalCodes}</p>
                <p>Активировано кодов: ${activeCount}</p>
                <p>Неудачные коды: ${failedCodes.length}</p>
            `;
        }

        if (failedText) {
            failedText.innerHTML = failedCodes.length > 0 ? `
                <ul>
                    ${failedCodes.map(code => `<li>${code}</li>`).join('')}
                </ul>
            ` : 'Нет неудачных кодов';
        }

        // Обновляем информационное сообщение
        if (infoMessage) {
            switch (messageType) {
                case 'saved':
                    infoMessage.textContent = 'Коды сохранены.';
                    infoMessage.style.color = '#4CAF50'; // Зеленый цвет для сохранения
                    break;
                case 'completed':
                    infoMessage.textContent = 'Все коды активированы, добавьте новые коды.';
                    infoMessage.style.color = '#ef5d5d'; // Красный цвет для завершения
                    break;
                case 'started':
                    infoMessage.textContent = 'Активация кодов началась.';
                    infoMessage.style.color = '#ccc'; // Серый цвет по умолчанию
                    break;
                case 'stopped':
                    infoMessage.textContent = 'Активация кодов остановлена.';
                    infoMessage.style.color = '#ccc'; // Серый цвет по умолчанию
                    break;
                default:
                    if (totalCodes === 0) {
                        infoMessage.textContent = 'Введите коды в поле ниже и нажмите "Сохранить коды". Если коды закончились, вы увидите сообщение об этом.';
                        infoMessage.style.color = '#ccc'; // Серый цвет по умолчанию
                    } else {
                        infoMessage.textContent = 'Введите коды в поле ниже и нажмите "Сохранить коды".';
                        infoMessage.style.color = '#ccc'; // Серый цвет по умолчанию
                    }
                    break;
            }
        }
    }

    // Обновление данных в localStorage
    function updateLocalStorage() {
        localStorage.setItem('codes', JSON.stringify(codes));
        localStorage.setItem('failedCodes', JSON.stringify(failedCodes));
        localStorage.setItem('currentIndex', currentIndex);
        localStorage.setItem('activeCount', activeCount);
        localStorage.setItem('infoMessageType', infoMessageType);
        localStorage.setItem('isActivating', JSON.stringify(isActivating));
    }

    // Загрузка данных из localStorage
    let codes = JSON.parse(localStorage.getItem('codes') || '[]');
    let failedCodes = JSON.parse(localStorage.getItem('failedCodes') || '[]');
    let currentIndex = parseInt(localStorage.getItem('currentIndex') || '0', 10);
    let activeCount = parseInt(localStorage.getItem('activeCount') || '0', 10);
    let infoMessageType = localStorage.getItem('infoMessageType') || '';
    let isActivating = JSON.parse(localStorage.getItem('isActivating') || 'false');

    // Создаем панель состояния и получаем элементы управления
    const { statusText, codesInput, saveButton, deleteButton, toggleButton, failedText, infoMessage } = createStatusPanels();

    // Устанавливаем начальные значения
    codesInput.value = codes.join('\n');
    updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);

    // Обработчик для кнопки сохранения кодов
    saveButton.addEventListener('click', () => {
        codes = codesInput.value.split('\n').map(code => code.trim()).filter(code => code.length > 0);
        failedCodes = [];
        currentIndex = 0;
        activeCount = 0;
        infoMessageType = 'saved';
        updateLocalStorage();
        updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
    });

    // Обработчик для кнопки удаления кодов
    deleteButton.addEventListener('click', () => {
        if (confirm('Вы уверены, что хотите удалить все коды? Это действие нельзя отменить.')) {
            codes = [];
            failedCodes = [];
            currentIndex = 0;
            activeCount = 0;
            infoMessageType = ''; // Убираем сообщение об удалении
            updateLocalStorage();
            codesInput.value = ''; // Очищаем поле ввода кодов
            updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
        }
    });

    // Функция для активации кодов
    async function activateCodes() {
        try {
            if (currentIndex >= codes.length) {
                infoMessageType = 'completed';
                isActivating = false; // Останавливаем активацию
                updateLocalStorage();
                updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
                toggleButton.textContent = 'Начать активацию'; // Обновляем текст кнопки
                toggleButton.style.backgroundColor = '#4CAF50'; // Цвет кнопки для начала активации
                clearInterval(autoActivationIntervalId); // Останавливаем автоматическую активацию
                return;
            }

            const code = codes[currentIndex];

            // Проверяем, если находимся на странице активации
            const inputField = document.querySelector('input[name="key"]');
            if (inputField) {
                inputField.value = code;

                // Нажимаем кнопку активации
                const activateButton = document.querySelector('input[type="submit"][value="Активировать"]');
                if (!activateButton) throw new Error('Кнопка активации не найдена');
                activateButton.click();

                console.log(`Активирую код: ${code}`);

                // Ждем выполнения запроса и перехода на следующ страницу
                await waitFor(waitTime);
            }

            // Проверяем наличие сообщения об ошибке активации на странице
            const errorMessage = document.querySelector('.code-activation__error');
            if (errorMessage) {
                console.log(`Ошибка активации кода: ${code} - ${errorMessage.textContent.trim()}`);
                failedCodes.push(code);
                updateLocalStorage();
                updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
            }

            // Проверяем наличие сообщения об успешной активации на странице
            const successMessage = document.querySelector('.content-column p a');
            if (successMessage) {
                console.log(`Код успешно активирован: ${code}`);
            }

            // Проверяем наличие кнопки "Вернуться" и нажимаем её
            const returnButton = document.querySelector('input[type="submit"][value="Вернуться"]');
            if (returnButton) {
                console.log('Код активирован, нажимаю кнопку "Вернуться"');

                // Обновляем текущий индекс и количество активированных кодов
                currentIndex++;
                activeCount++;
                updateLocalStorage();
                updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);

                returnButton.click();

                // Ждем возврата на страницу ввода кода
                await waitFor(waitTime);
            }

        } catch (error) {
            console.error(`Ошибка при активации кода ${codes[currentIndex]}:`, error);
        } finally {
            // Перезагружаем страницу для продолжения
            if (isActivating) {
                setTimeout(() => {
                    window.location.reload();
                }, refreshInterval);
            }
        }
    }

    // Функция для имитации кликов
    function startAutoActivation() {
        autoActivationIntervalId = setInterval(() => {
            if (!isActivating) {
                clearInterval(autoActivationIntervalId);
                return;
            }
            activateCodes();
        }, clickInterval);
    }

    // Обработчик для кнопки переключения активации
    let autoActivationIntervalId;

    toggleButton.addEventListener('click', () => {
        if (codes.length === 0) {
            alert('Сначала введите и сохраните коды.');
            return;
        }

        if (isActivating) {
            isActivating = false;
            infoMessageType = 'stopped';
            updateLocalStorage();
            updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
            clearInterval(autoActivationIntervalId); // Останавливаем автоматическую активацию
            toggleButton.textContent = 'Начать активацию'; // Обновляем текст кнопки
            toggleButton.style.backgroundColor = '#4CAF50'; // Цвет кнопки для начала активации
        } else {
            isActivating = true;
            infoMessageType = 'started';
            updateLocalStorage();
            updateStatusPanel(activeCount, codes.length, failedCodes, infoMessageType);
            startAutoActivation(); // Запускаем автоматическую активацию
            toggleButton.textContent = 'Остановить активацию'; // Обновляем текст кнопки
            toggleButton.style.backgroundColor = '#e53935'; // Цвет кнопки для остановки активации
        }

        // Обновляем состояние кнопки
        toggleButton.style.color = '#fff';
    });

    // Устанавливаем начальные значения кнопок и состояния
    toggleButton.textContent = isActivating ? 'Остановить активацию' : 'Начать активацию';
    toggleButton.style.backgroundColor = isActivating ? '#e53935' : '#4CAF50';
    toggleButton.style.color = '#fff';
    if (isActivating) startAutoActivation(); // Запускаем автоматическую активацию при загрузке, если она была активирована
})();