antiDTF (Userscript)

Ограничь свое время на DTF. Userscript version. Автор: Dude

// ==UserScript==
// @name         antiDTF (Userscript)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Ограничь свое время на DTF. Userscript version. Автор: Dude
// @author       Dude (converted)
// @match        *://dtf.ru/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @run-at       document-idle
// @license MIT 
// ==/UserScript==

(async function() {
    'use strict';

    // --- Configuration Keys ---
    const KEY_DAILY_LIMIT = 'antiDTF_dailyLimit';
    const KEY_START_TIMESTAMP = 'antiDTF_startTimestamp';
    const KEY_LAST_RESET = 'antiDTF_lastReset';

    // --- Helper Functions for Storage ---
    async function getConfig(key, defaultValue = null) {
        return await GM_getValue(key, defaultValue);
    }

    async function setConfig(key, value) {
        await GM_setValue(key, value);
    }

    // --- Blocked Page Styling and Content ---
    const blockedStyles = `
        body {
            background: #ff00ff !important;
            color: #ffff00 !important;
            font-family: 'Comic Sans MS', cursive, sans-serif !important;
            text-align: center !important;
            font-size: 32px !important;
            margin: 0 !important;
            padding: 0 !important;
            height: 100vh !important;
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
            overflow: hidden !important;
        }
        /* Hide everything else just in case */
        body > *:not(#antiDTF-blocked-message) {
            display: none !important;
        }
    `;
    const blockedHTML = `<div id="antiDTF-blocked-message">Лимит DTF на сегодня исчерпан. Пиздуй работать.</div>`;

    // --- Core Time Limit Check Logic ---
    async function checkTimeLimit() {
        const dailyLimit = await getConfig(KEY_DAILY_LIMIT);
        let startTimestamp = await getConfig(KEY_START_TIMESTAMP);
        let lastReset = await getConfig(KEY_LAST_RESET);

        // If limit is not set or invalid, do nothing
        if (dailyLimit === null || isNaN(dailyLimit) || dailyLimit <= 0) {
            console.log("antiDTF: Limit not set or invalid.");
            return false; // Not blocked
        }

        const limitMinutes = parseInt(dailyLimit, 10);
        const nowDate = new Date().toDateString();

        // Check if it's a new day
        if (lastReset !== nowDate) {
            console.log("antiDTF: New day detected. Resetting timer.");
            startTimestamp = Date.now();
            await setConfig(KEY_LAST_RESET, nowDate);
            await setConfig(KEY_START_TIMESTAMP, startTimestamp);
            console.log(`antiDTF: Timer reset. Limit: ${limitMinutes} minutes.`);
            return false; // Not blocked yet today
        }

        // Check if startTimestamp is valid (necessary after first setting the limit)
        if (!startTimestamp) {
             console.log("antiDTF: Start timestamp missing for today. Initializing.");
             startTimestamp = Date.now();
             await setConfig(KEY_START_TIMESTAMP, startTimestamp);
             return false; // Not blocked yet
        }

        // Calculate elapsed time
        const elapsedMs = Date.now() - startTimestamp;
        const elapsedMinutes = Math.floor(elapsedMs / 60000);

        console.log(`antiDTF: Time check - Elapsed: ${elapsedMinutes} min / Limit: ${limitMinutes} min`);

        // Check if limit is exceeded
        if (elapsedMinutes >= limitMinutes) {
            console.log("antiDTF: Daily limit exceeded. Blocking page.");
            blockPage();
            return true; // Blocked
        }

        return false; // Not blocked
    }

    // --- Function to Block the Page ---
    function blockPage() {
        // Stop further loading/scripts if possible
        try { window.stop(); } catch (e) { console.warn("antiDTF: Could not stop window loading.", e); }

        // Apply styles first
        GM_addStyle(blockedStyles);

        // Replace body content
        document.body.innerHTML = blockedHTML;

        // Set title
        document.title = "antiDTF - Лимит исчерпан";
    }

    // --- Settings via Menu Commands (Replaces Popup) ---

    // 1. Set/Change Limit
    GM_registerMenuCommand("antiDTF: Установить/Изменить лимит", async () => {
        const currentLimit = await getConfig(KEY_DAILY_LIMIT, '');
        const newLimitStr = prompt(`Введите дневной лимит времени на DTF в минутах.\n(Текущий: ${currentLimit || 'не установлен'})\nВведите 0 или оставьте пустым для снятия лимита.`, currentLimit);

        if (newLimitStr === null) return; // User cancelled

        const newLimit = parseInt(newLimitStr.trim(), 10);

        if (!isNaN(newLimit) && newLimit > 0) {
            await setConfig(KEY_DAILY_LIMIT, newLimit);
            // Reset timer immediately when limit is set/changed
            const today = new Date().toDateString();
            await setConfig(KEY_LAST_RESET, today);
            await setConfig(KEY_START_TIMESTAMP, Date.now());
            alert(`antiDTF: Лимит установлен на ${newLimit} минут в день.\nТаймер сброшен на сегодня.`);
            // Reload to apply immediately (especially important if currently blocked)
            location.reload();
        } else if (newLimitStr.trim() === '' || newLimit === 0) {
             await setConfig(KEY_DAILY_LIMIT, null); // Use null to indicate no limit
             await setConfig(KEY_START_TIMESTAMP, null);
             await setConfig(KEY_LAST_RESET, '');
             alert("antiDTF: Лимит снят.");
             // Reload to unblock if currently blocked
             location.reload();
        } else {
            alert("antiDTF: Ошибка. Введите положительное число минут или 0 для снятия лимита.");
        }
    });

    // 2. Extend Limit ("Продлить как лох")
    GM_registerMenuCommand("antiDTF: Продлить как лох", async () => {
        const currentLimit = await getConfig(KEY_DAILY_LIMIT);
        if (currentLimit === null) {
            alert("antiDTF: Сначала установите основной лимит.");
            return;
        }

        const addMinutesStr = prompt(`На сколько минут продлить сегодняшний лимит? (Текущий: ${currentLimit} минут)`);
        if (addMinutesStr === null) return; // User cancelled

        const addMinutes = parseInt(addMinutesStr.trim(), 10);

         if (!isNaN(addMinutes) && addMinutes > 0) {
            const newLimit = (parseInt(currentLimit, 10) || 0) + addMinutes;
            await setConfig(KEY_DAILY_LIMIT, newLimit);
            alert(`antiDTF: Лимит продлен на ${addMinutes} минут.\nНовый лимит на сегодня: ${newLimit} минут.\nСтраница будет перезагружена.`);
            // Don't reset startTimestamp here, just increase the ceiling for today
            location.reload(); // Reload to potentially unblock or continue browsing
         } else {
             alert("antiDTF: Ошибка. Введите положительное число минут.");
         }
     });

    // 3. Check Status
    GM_registerMenuCommand("antiDTF: Проверить статус", async () => {
        const dailyLimit = await getConfig(KEY_DAILY_LIMIT);
        let startTimestamp = await getConfig(KEY_START_TIMESTAMP);
        let lastReset = await getConfig(KEY_LAST_RESET);

        if (dailyLimit === null) {
            alert("antiDTF: Лимит времени не установлен.");
            return;
        }

        const limitMinutes = parseInt(dailyLimit, 10);
        const nowDate = new Date().toDateString();

        if (lastReset !== nowDate || !startTimestamp) {
            // Handles both new day and cases where start timestamp wasn't set yet
            alert(`antiDTF:\nЛимит: ${limitMinutes} минут в день.\nТаймер на сегодня еще не запущен (начнет отсчет при следующем взаимодействии с сайтом).`);
            return;
        }

        const elapsedMs = Date.now() - startTimestamp;
        const elapsedMinutes = Math.floor(elapsedMs / 60000);
        const remainingMinutes = Math.max(0, limitMinutes - elapsedMinutes);
        const remainingSecondsTotal = Math.max(0, (limitMinutes * 60) - Math.floor(elapsedMs / 1000));
        const remainingSecs = remainingSecondsTotal % 60;
        const remainingMins = Math.floor(remainingSecondsTotal / 60);


        alert(`antiDTF Статус:\nЛимит: ${limitMinutes} минут.\nИспользовано сегодня: ${elapsedMinutes} минут.\nОсталось: ${remainingMins} мин ${remainingSecs < 10 ? '0' : ''}${remainingSecs} сек.`);
   });


    // --- Initial Execution ---
    console.log("antiDTF Userscript running on:", window.location.href);
    // Run the check when the script loads
    await checkTimeLimit();

    // Note: The script runs on 'document-idle', so the page content might already be visible
    // for a moment before being blocked if the limit is exceeded. The check runs on every
    // matching page load/navigation.

})();