Duohelper

Monitor Ping and FPS, track session time, and reset password securely.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Duohelper
// @namespace    http://tampermonkey.net/
// @version      1.2.0
// @description  Monitor Ping and FPS, track session time, and reset password securely.
// @author       Your Name
// @match        https://*.duolingo.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// ==/UserScript==

(function() {
    'use strict';

    let basePing = 100; // Basic Ping (ms)
    let baseFps = 60; // Basic FPS

    let ping = basePing; // Current ping value (ms)
    let fps = baseFps; // Current FPS value
    let sessionStartTime = Date.now(); // Session start time

    // Function to check if localStorage is supported
    function isLocalStorageSupported() {
        try {
            const testKey = '__testKey';
            localStorage.setItem(testKey, testKey);
            localStorage.removeItem(testKey);
            return true;
        } catch (error) {
            return false;
        }
    }

    // Check if localStorage is supported
    if (!isLocalStorageSupported()) {
        console.error('LocalStorage is not supported.');
        return;
    }

    // Create and append CSS styles
    const style = document.createElement('style');
    style.textContent = `
        #performanceMonitor {
            position: fixed;
            top: 10px;
            right: 10px;
            padding: 8px;
            border: 5px solid #ddd;
            background-color: #0a0a0a;
            color: white;
            border-radius: 8px;
            font-family: Arial, sans-serif;
            font-size: 14px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
            width: 200px;
            text-align: left;
            overflow: auto;
            cursor: pointer;
            z-index: 9999;
            transition: opacity 0.3s ease-in-out;
        }
        #performanceMonitor button {
            display: block;
            margin-bottom: 5px;
            cursor: pointer;
            background-color: #444;
            color: white;
            border: none;
            border-radius: 4px;
            padding: 4px 8px;
            font-size: 12px;
            transition: background-color 0.3s;
        }
        #performanceMonitor button:hover {
            background-color: #666;
        }
        #performanceContent {
            display: block;
        }
        .modal {
            position: fixed;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.9);
            color: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            z-index: 10000;
            display: none;
        }
        .modal h3 {
            margin-bottom: 10px;
        }
        .modal label {
            display: block;
            margin-bottom: 5px;
        }
        .modal input[type="text"], .modal input[type="password"], .modal input[type="email"] {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            border: 1px solid #666;
            border-radius: 4px;
            background-color: #333;
            color: white;
        }
        .modal button {
            margin-top: 10px;
            padding: 8px 16px;
            background-color: #1cb0f6;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        .modal button:hover {
            background-color: #0a7bb0;
        }
    `;
    document.head.appendChild(style);

    // Create container for display
    const container = document.createElement('div');
    container.id = 'performanceMonitor';
    container.title = 'Click to hide/show';
    document.body.appendChild(container);

    // Create content wrapper
    const contentWrapper = document.createElement('div');
    contentWrapper.id = 'performanceContentWrapper';
    container.appendChild(contentWrapper);

    // Create content area
    const content = document.createElement('div');
    content.id = 'performanceContent';
    contentWrapper.appendChild(content);

    // Create toggle button
    const toggleButton = document.createElement('button');
    toggleButton.textContent = 'Hide';
    toggleButton.addEventListener('mouseover', () => {
        toggleButton.style.backgroundColor = '#666';
    });
    toggleButton.addEventListener('mouseout', () => {
        toggleButton.style.backgroundColor = '#444';
    });
    toggleButton.addEventListener('click', () => {
        const isVisible = contentWrapper.style.display !== 'none';
        contentWrapper.style.display = isVisible ? 'none' : 'block';
        toggleButton.textContent = isVisible ? 'Show' : 'Hide';
    });
    container.appendChild(toggleButton);

    // Create reload button
    const reloadButton = document.createElement('button');
    reloadButton.textContent = 'Reload Page';
    reloadButton.addEventListener('click', () => {
        location.reload();
    });
    contentWrapper.appendChild(reloadButton);

    // Function to measure ping
    async function measurePing(url) {
        try {
            const start = performance.now();
            const response = await fetch(url, { method: 'HEAD' });
            await response;
            const end = performance.now();
            const pingValue = Math.round(end - start) + ' ms';
            updateDisplay(pingValue);
        } catch (error) {
            console.error('Ping Error:', error);
            updateDisplay('Error');
        }
    }

    // Function to measure FPS
    let lastFrameTime = performance.now();
    let frameCount = 0;

    function measureFPS() {
        const now = performance.now();
        const delta = now - lastFrameTime;
        frameCount++;

        if (delta >= 1000) {
            const fpsValue = Math.round((frameCount * 1000) / delta);
            updateDisplay(null, fpsValue);
            frameCount = 0;
            lastFrameTime = now;
        }

        requestAnimationFrame(measureFPS);
    }

    // Function to update display
    function updateDisplay(pingValue, fpsValue) {
        if (pingValue !== undefined) {
            ping = pingValue;
        }
        if (fpsValue !== undefined) {
            fps = fpsValue;
        }

        const elapsedTime = formatSessionTime(Date.now() - sessionStartTime);

        const display = document.getElementById('performanceContent');
        display.innerHTML = `
            <div><strong>Ping:</strong> ${ping}</div>
            <div><strong>FPS:</strong> ${fps}</div>
            <div><strong>Session Time:</strong> ${elapsedTime}</div>
            <button id="resetPassword" style="margin-top: 5px;">Reset Password</button>
        `;
        document.getElementById('resetPassword').addEventListener('click', showResetPasswordModal);
    }

    // Format session time in HH:mm:ss format
    function formatSessionTime(milliseconds) {
        let seconds = Math.floor(milliseconds / 1000);
        const hours = Math.floor(seconds / 3600);
        seconds %= 3600;
        const minutes = Math.floor(seconds / 60);
        seconds %= 60;
        return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
    }

    // Modal to reset password
    const resetPasswordModal = document.createElement('div');
    resetPasswordModal.className = 'modal';
    resetPasswordModal.innerHTML = `
        <h3>Reset Password</h3>
        <div>
            <label for="resetEmail">Email:</label>
            <input type="email" id="resetEmail" />
        </div>
        <button id="sendResetEmail" style="margin-top: 10px;">Send Reset Email</button>
        <button id="cancelResetPassword" style="margin-top: 10px;">Cancel</button>
    `;
    document.body.appendChild(resetPasswordModal);

    // Show reset password modal function
    function showResetPasswordModal() {
        resetPasswordModal.style.display = 'block';
    }

    // Hide reset password modal function
    function hideResetPasswordModal() {
        resetPasswordModal.style.display = 'none';
    }

    // Cancel reset password modal function
    document.getElementById('cancelResetPassword').addEventListener('click', hideResetPasswordModal);

    // Send reset email function
    document.getElementById('sendResetEmail').addEventListener('click', () => {
        const email = document.getElementById('resetEmail').value;

        if (email && validateEmail(email)) {
            // Simulate sending a reset password email
            console.log('Sending password reset email to:', email);
            alert('A password reset email has been sent to ' + email);
            hideResetPasswordModal();
        } else {
            alert('Please enter a valid email address.');
        }
    });

    // Validate email address
    function validateEmail(email) {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(email);
    }

    // Start measuring ping and FPS
    setInterval(() => {
        measurePing('https://www.duolingo.com');
    }, 5000); // Measure ping every 5 seconds

    requestAnimationFrame(measureFPS); // Start measuring FPS

    // Initialize display
    updateDisplay(basePing, baseFps); // Initial display update
})();